En-tête de tableau pour rester fixe en haut lorsque l'utilisateur le fait défiler hors de vue avec jQuery

146

J'essaie de concevoir un tableau HTML où l'en-tête restera en haut de la page lorsque ET UNIQUEMENT lorsque l'utilisateur le fait défiler hors de vue. Par exemple, le tableau peut être à 500 pixels de la page, comment faire pour que si l'utilisateur fait défiler l'en-tête hors de la vue (le navigateur détecte qu'il n'est plus dans la vue Windows), il restera en haut ? N'importe qui peut me donner une solution Javascript à cela?

<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>
</table>

Donc, dans l'exemple ci-dessus, je veux <thead>que la page défile avec la page si elle disparaît.

IMPORTANT: Je ne cherche PAS une solution où le <tbody>aura une barre de défilement (débordement: auto).

Sam Dufel
la source
2
dupliquer? stackoverflow.com/questions/1030043
Brad Tofel
J'ai répondu à cela pour une autre question, veuillez jeter un coup d'œil. stackoverflow.com/a/56764334/9388978
Ersel Aktas

Réponses:

131

Vous feriez quelque chose comme ça en appuyant sur le scrollgestionnaire d'événements windowet en utilisant un autre tableavec une position fixe pour afficher l'en-tête en haut de la page.

HTML:

<table id="header-fixed"></table>

CSS:

#header-fixed {
    position: fixed;
    top: 0px; display:none;
    background-color:white;
}

JavaScript:

var tableOffset = $("#table-1").offset().top;
var $header = $("#table-1 > thead").clone();
var $fixedHeader = $("#header-fixed").append($header);

$(window).bind("scroll", function() {
    var offset = $(this).scrollTop();

    if (offset >= tableOffset && $fixedHeader.is(":hidden")) {
        $fixedHeader.show();
    }
    else if (offset < tableOffset) {
        $fixedHeader.hide();
    }
});

Cela affichera la tête de table lorsque l'utilisateur fait défiler suffisamment bas pour masquer la tête de table d'origine. Il se cachera à nouveau lorsque l'utilisateur aura à nouveau fait défiler la page vers le haut.

Exemple de travail: http://jsfiddle.net/andrewwhitaker/fj8wM/

Andrew Whitaker
la source
60
J'y pensais, mais que se passe-t-il si la largeur des colonnes d'en-tête change en fonction du contenu? À moins que les largeurs de colonne ne soient fixes, votre ligne d'en-tête pourrait ne pas être alignée avec les lignes de contenu. Juste une pensée.
Yzmir Ramirez
16
cet exemple ne fonctionne pas si les noms des en-têtes de colonne sont plus courts que les valeurs des données de colonne. Essayez de changer ce violon pour avoir des valeurs comme infoooooooo au lieu d'informations. Je pense à une sorte de largeur codée en dur qui est définie lors du clonage de la table.
whiterook6
6
Cela présente des limitations majeures, dont la moindre concerne l'utilisation de la table dans un conteneur autre que window. mkoryak.github.io/floatThead a une solution plus généralement applicable.
Beurk
13
Cela pourrait aider tous ceux qui ont besoin de largeurs dynamiques, c'est ce que j'ai fini par faire, c'est un fork de @AndrewWhitaker: jsfiddle.net/noahkoch/wLcjh/1
Noah Koch
1
L'en-tête fixe @NoahKoch utilisant votre solution peut ne pas être aussi large que la tête d'origine lorsque les cellules d'origine ont un remplissage. J'ai amélioré votre solution pour ajouter un remplissage aux cellules dupliquées. Fourchette de JSFiddle: jsfiddle.net/1n23m69u/2
fandasson
47

CSS pur (sans support IE11):

table th {
    position: -webkit-sticky; // this is for all Safari (Desktop & iOS), not for Chrome
    position: sticky;
    top: 0;
    z-index: 5;
    background: #fff;
}
Ihor Zenich
la source
1
Je ne vois même pas cela fonctionner dans Chrome. Les outils d'inspection s'affichent -webkit-stickycomme une valeur non valide pour position.
carménisme
@carmenism -webkit-stickyest pour Safari (bureau et iOS), pas pour Chrome. position: stickyfonctionne dans Chrome à partir de la version 56. Vous devez définir les DEUX règles: -webkit-stickyet stickyexactement dans le même ordre que dans mon exemple de code. Safari obtient webkit-stickyet tous les autres navigateurs l'écrasent avec sticky.
Ihor Zenich
2
Je n'ai pas pu faire fonctionner cela. D'un google rapide, il semble position: stickyne pas fonctionner avec les éléments de tableau.
rjh le
3
postuler à th a fonctionné pour moi: table thead tr th {...}
nurp
1
Vous devez l'appliquer au th car il ne fonctionnera pas sur la tête ni sur le tr
helado
46

Eh bien, j'essayais d'obtenir le même effet sans recourir à des colonnes de taille fixe ou avoir une hauteur fixe pour toute la table.

La solution que j'ai trouvée est un hack. Il consiste à dupliquer la table entière puis à cacher tout sauf l'en-tête, et à en faire une position fixe.

HTML

<div id="table-container">
<table id="maintable">
    <thead>
        <tr>
            <th>Col1</th>
            <th>Col2</th>
            <th>Col3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>some really long line here instead</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
                <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
                <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
    </tbody>
</table>
<div id="bottom_anchor"></div>
</div>

CSS

body { height: 1000px; }
thead{
    background-color:white;
}

javascript

function moveScroll(){
    var scroll = $(window).scrollTop();
    var anchor_top = $("#maintable").offset().top;
    var anchor_bottom = $("#bottom_anchor").offset().top;
    if (scroll>anchor_top && scroll<anchor_bottom) {
    clone_table = $("#clone");
    if(clone_table.length == 0){
        clone_table = $("#maintable").clone();
        clone_table.attr('id', 'clone');
        clone_table.css({position:'fixed',
                 'pointer-events': 'none',
                 top:0});
        clone_table.width($("#maintable").width());
        $("#table-container").append(clone_table);
        $("#clone").css({visibility:'hidden'});
        $("#clone thead").css({'visibility':'visible','pointer-events':'auto'});
    }
    } else {
    $("#clone").remove();
    }
}
$(window).scroll(moveScroll); 

Voir ici: http://jsfiddle.net/QHQGF/7/

Edit: a mis à jour le code afin que la thead puisse recevoir des événements de pointeur (donc les boutons et les liens dans l'en-tête fonctionnent toujours). Cela résout le problème signalé par luhfluh et Joe M.

Nouveau jsfiddle ici: http://jsfiddle.net/cjKEx/

entropie
la source
3
J'ai essayé cela en premier, le problème avec cela est que la taille des éléments dans l'en-tête dépend du contenu du tableau. Si vous avez une ligne avec un gros contenu, la colonne entière, y compris l'en-tête, augmentera. Si vous ne clonez que la tête, vous perdez ces informations et vous n'obtenez pas l'effet souhaité. Voir le commentaire d'Yzmir Ramirez sur la réponse acceptée. C'est le seul moyen que j'ai trouvé qui fonctionne sans colonnes à largeur fixe. Ce n'est pas propre, je sais, c'est ainsi que j'ai dit que c'était un hack.
entropie du
1
Oh je l'ai. Cette méthode est excellente car elle fonctionne avec des colonnes fluides, j'ai un peu cherché sur Google et je n'ai pas pu en trouver une autre avec cette fonctionnalité. Quoi qu'il en soit, si je veux le faire d'une manière ou d'une autre, je le mentionnerai ici
M2_
1
@luhfluh, oui, le problème était dû aux événements de pointeur: aucun dans la table clonée. Ceci est utilisé pour que les clics passent par le clone et la table d'origine. Le retourner dans l'en-tête de la table clonée afin que l'en-tête (et uniquement l'en-tête) soit cliquable résout le problème. J'ai mis à jour mon message pour refléter ceci :)
entropie
4
problème d'ajout de bordure sur <thead> <th>
Jam Ville
1
@JamVille Parce que la table clonée a visibility: hidden. Vous pouvez masquer seulement #clone tbodyet après cela, vous pouvez définir la frontière ... Violon de travail: jsfiddle.net/QHQGF/1707
Lajdák Marek
26

J'ai écrit un plugin qui fait cela. J'y travaille depuis environ un an maintenant et je pense qu'il gère assez bien tous les cas d'angle:

  • défilement dans un conteneur avec débordement
  • défilement dans une fenêtre
  • prendre soin de ce qui se passe lorsque vous redimensionnez la fenêtre
  • garder vos événements liés à l'en-tête
  • plus important encore, cela ne vous oblige pas à modifier le css de votre table pour le faire fonctionner

Voici quelques démos / documents:
http://mkoryak.github.io/floatThead/

mkoryak
la source
grand effort, mais ne fonctionne pas avec IE 10 et a quelques bizarreries sur le redimensionnement de fenêtres sur firefox23 / ubuntu.
Janning
2
FYI: j'ai corrigé les problèmes avec IE9 et 10 dans la dernière version.
mkoryak
2
Pouvez-vous créer une version qui ne nécessite pas jQuery?
Curtis W
2
probablement parce qu'il n'utilise pas jquery ... et non - je ne ferai pas une version qui n'utilise pas jquery.
mkoryak
1
J'utilise un simple plugin jQery tablesorter et selon votre FAQ, votre plugin n'aime pas la plupart des règles CSS comme #sortable td {..} et ainsi de suite. J'ai essayé d'ajuster un peu mais je n'ai pas réussi à le faire fonctionner.
masche
25

J'ai pu résoudre le problème de modification de la largeur des colonnes. J'ai commencé avec la solution d'Andrew ci-dessus (merci beaucoup!), Puis j'ai ajouté une petite boucle pour définir les largeurs des td clonés:

$("#header-fixed td").each(function(index){
    var index2 = index;
    $(this).width(function(index2){
        return $("#table-1 td").eq(index).width();
    });
});

Cela résout le problème sans avoir à cloner la table entière et à masquer le corps. Je suis tout nouveau dans JavaScript et jQuery (et pour stack overflow), donc tous les commentaires sont appréciés.

Rockusbacchus
la source
4
Cela fonctionnait bien mais j'avais besoin d'ajouter la ligne suivante $ ("# header-fixed"). Width ($ ("# table-1"). Width ()); pour que les colonnes s'alignent correctement.
Ilya Fedotov
17

C'est de loin la meilleure solution que j'ai trouvée pour avoir un en-tête de table fixe.

MISE À JOUR 5/11: Correction d'un bug de défilement horizontal comme indiqué par Kerry Johnson

Codepen: https://codepen.io/josephting/pen/demELL

;(function($) {
   $.fn.fixMe = function() {
      return this.each(function() {
         var $this = $(this),
            $t_fixed;
         function init() {
            $this.wrap('<div class="container" />');
            $t_fixed = $this.clone();
            $t_fixed.find("tbody").remove().end().addClass("fixed").insertBefore($this);
            resizeFixed();
         }
         function resizeFixed() {
           $t_fixed.width($this.outerWidth());
            $t_fixed.find("th").each(function(index) {
               $(this).css("width",$this.find("th").eq(index).outerWidth()+"px");
            });
         }
         function scrollFixed() {
            var offsetY = $(this).scrollTop(),
            offsetX = $(this).scrollLeft(),
            tableOffsetTop = $this.offset().top,
            tableOffsetBottom = tableOffsetTop + $this.height() - $this.find("thead").height(),
            tableOffsetLeft = $this.offset().left;
            if(offsetY < tableOffsetTop || offsetY > tableOffsetBottom)
               $t_fixed.hide();
            else if(offsetY >= tableOffsetTop && offsetY <= tableOffsetBottom && $t_fixed.is(":hidden"))
               $t_fixed.show();
            $t_fixed.css("left", tableOffsetLeft - offsetX + "px");
         }
         $(window).resize(resizeFixed);
         $(window).scroll(scrollFixed);
         init();
      });
   };
})(jQuery);

$(document).ready(function(){
   $("table").fixMe();
   $(".up").click(function() {
      $('html, body').animate({
      scrollTop: 0
   }, 2000);
 });
});
body{
  font:1.2em normal Arial,sans-serif;
  color:#34495E;
}

h1{
  text-align:center;
  text-transform:uppercase;
  letter-spacing:-2px;
  font-size:2.5em;
  margin:20px 0;
}

.container{
  width:90%;
  margin:auto;
}

table{
  border-collapse:collapse;
  width:100%;
}

.blue{
  border:2px solid #1ABC9C;
}

.blue thead{
  background:#1ABC9C;
}

.purple{
  border:2px solid #9B59B6;
}

.purple thead{
  background:#9B59B6;
}

thead{
  color:white;
}

th,td{
  text-align:center;
  padding:5px 0;
}

tbody tr:nth-child(even){
  background:#ECF0F1;
}

tbody tr:hover{
background:#BDC3C7;
  color:#FFFFFF;
}

.fixed{
  top:0;
  position:fixed;
  width:auto;
  display:none;
  border:none;
}

.scrollMore{
  margin-top:600px;
}

.up{
  cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>&darr; SCROLL &darr;</h1>
<table class="blue">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>MaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>

<h1 class="scrollMore">&darr; SCROLL MORE &darr;</h1>
<table class="purple">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>
<h1 class="up scrollMore">&uarr; UP &uarr;</h1>

josephting
la source
J'ai corrigé ce script afin qu'il puisse gérer les éléments <th> qui ont une bordure et un remplissage (sinon, il définit les largeurs d'en-tête fixes <th> trop larges). Changez simplement outerWidthen widthdans la définition de la fonction resizeFixed ().
alanng le
Vous devrez peut-être également ajouter une propriété CSS z-indexà un nombre positif sur la .fixedclasse afin que les objets rendus après le chargement de la page dans le tableau ne flottent pas au-dessus de l'en-tête fixe lorsque vous faites défiler.
alanng le
Simple et utile.
RitchieD
comment gérer dynamiquement la position supérieure. Disons que j'ai besoin de faire défiler jusqu'à sous le contenu de l'en-tête fixe de ma page principale. .fixed {top: 0;} .
VijayVishnu
2
@KerryJohnson Merci pour la note. J'ai apporté quelques modifications afin qu'il prenne en charge le défilement horizontal et les largeurs de colonne dynamiques.
josephting
7

La meilleure solution est d'utiliser ce plugin jquery:

https://github.com/jmosbech/StickyTableHeaders

Ce plugin a très bien fonctionné pour nous et nous avons essayé beaucoup d'autres solutions. Nous l'avons testé dans IE, Chrome et Firefox

Janning
la source
Connaissez-vous une solution qui préserve également la fonctionnalité des contrôles liés aux données knockout dans l'en-tête?
Csaba Toth
Cela n'a pas fonctionné pour moi: les en-têtes sont en dehors du tableau et collent en haut du navigateur (fenêtre), même avec l'option "scrollableArea". J'ai vu que cela avait été mentionné auparavant sans commentaires supplémentaires. Peut-être qu'il a besoin d'un CSS qu'il utilise et qu'il n'est pas disponible pour le faire fonctionner.
Exel Gamboa
6

Il existe déjà de très bonnes solutions ici. Mais l'une des solutions CSS les plus simples que j'utilise dans ces situations est la suivante:

table {
  /* Not required only for visualizing */
  border-collapse: collapse;
  width: 100%;
}

table thead tr th {
  /* Important */
  background-color: red;
  position: sticky;
  z-index: 100;
  top: 0;
}

td {
  /* Not required only for visualizing */
  padding: 1em;
}
<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>
</table>

Parce qu'il n'y a aucune exigence pour JavaScript, cela simplifie considérablement la situation. Vous devez essentiellement vous concentrer sur la deuxième règle CSS, qui contient les conditions pour garantir que la tête du tableau reste en haut, quel que soit l'espace de défilement.

Elaborer chacune des règles en détail. positionest destiné à indiquer au navigateur que l'objet principal, sa ligne et ses cellules doivent tous rester en haut. Cela doit nécessairement être accompagné de top, qui spécifie au navigateur que la tête restera en haut de la page ou de la fenêtre. De plus, vous pouvez ajouter z-indexpour vous assurer que le contenu de la tête reste toujours en haut.

La couleur de fond est simplement pour illustrer le point. Vous n'avez pas besoin d'utiliser de JavaScript supplémentaire pour obtenir cet effet. Ceci est pris en charge dans la plupart des principaux navigateurs après 2016.

Srivats Shankar
la source
1
imo la réponse simple et la plus propre, il y a toujours un moyen simple de résoudre un problème, c'est le cas. Même si j'utilise ng-repeat avec angularjs, cela fonctionne comme un charme.
David Castro
5

J'ai trouvé une bibliothèque jQuery simple appelée Sticky Table Headers. Deux lignes de code et ça a fait exactement ce que je voulais. Les solutions ci-dessus ne gèrent pas les largeurs de colonne, donc si vous avez des cellules de tableau qui prennent beaucoup d'espace, la taille résultante de l'en-tête persistant ne correspondra pas à la largeur de votre tableau.

http://plugins.jquery.com/StickyTableHeaders/

Informations d'utilisation ici: https://github.com/jmosbech/StickyTableHeaders

Lok Yan Wong
la source
3

Eh bien, après avoir examiné toutes les solutions disponibles, j'ai écrit un plugin qui peut geler n'importe quelle ligne (pas seulement la th) en haut de la page ou du conteneur. C'est très simple et très rapide. Sentez-vous libre de l'utiliser. http://maslianok.github.io/stickyRows/

Vitalii Maslianok
la source
3

vous pouvez utiliser cette approche, pur HTML et CSS sans JS :)

.table-fixed-header {
  display: flex;
  justify-content: space-between;
  margin-right: 18px
}

.table-fixed {
  display: flex;
  justify-content: space-between;
  height: 150px;
  overflow: scroll;
}

.column {
  flex-basis: 24%;
  border-radius: 5px;
  padding: 5px;
  text-align: center;
}
.column .title {
  border-bottom: 2px grey solid;
  border-top: 2px grey solid;
  text-align: center;
  display: block;
  font-weight: bold;
}

.cell {
  padding: 5px;
  border-right: 1px solid;
  border-left: 1px solid;
}

.cell:nth-of-type(even) {
  background-color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Fixed header Bin</title>
</head>
<body>
<div class="table-fixed-header">
    
    <div class="column">
      <span class="title">col 1</span>
    </div>
    <div class="column">
      <span class="title">col 2</span>
    </div>
    <div class="column">
      <span class="title">col 3</span>
    </div>
    <div class="column">
      <span class="title">col 4</span>
    </div>
    
  </div>
  
  <div class="table-fixed">
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">beta</div>
      <div class="cell">beta</div>
      <div class="cell">beta</div>
      
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
  </div>
</body>
</html>

xelilof
la source
3

J'ai trouvé une solution simple sans utiliser JQuery et en utilisant uniquement CSS .

Vous devez mettre le contenu fixe dans les balises 'th' et ajouter le CSS

table th {
    position:sticky;
    top:0;
    z-index:1;
    border-top:0;
    background: #ededed;
}
   

Les propriétés position, z-index et top suffisent. Mais vous pouvez appliquer le reste pour donner une meilleure vue.

Abhi Das
la source
2

J'ai moi aussi rencontré les mêmes problèmes avec le formatage de la bordure qui n'était pas affiché en utilisant le code d'entrophy, mais quelques petites corrections et maintenant le tableau est extensible et affiche toutes les règles de style css que vous pouvez ajouter.

au css ajouter:

#maintable{width: 100%}    

alors voici le nouveau javascript:

    function moveScroll(){
    var scroll = $(window).scrollTop();
    var anchor_top = $("#maintable").offset().top;
    var anchor_bottom = $("#bottom_anchor").offset().top;
    if (scroll > anchor_top && scroll < anchor_bottom) {
        clone_table = $("#clone");
        if(clone_table.length === 0) {          
            clone_table = $("#maintable").clone();
            clone_table.attr({id: "clone"})
            .css({
                position: "fixed",
                "pointer-events": "none",
                 top:0
            })
            .width($("#maintable").width());

            $("#table-container").append(clone_table);
            // dont hide the whole table or you lose border style & 
            // actively match the inline width to the #maintable width if the 
            // container holding the table (window, iframe, div) changes width          
            $("#clone").width($("#maintable").width());
            // only the clone thead remains visible
            $("#clone thead").css({
                visibility:"visible"
            });
            // clone tbody is hidden
            $("#clone tbody").css({
                visibility:"hidden"
            });
            // add support for a tfoot element
            // and hide its cloned version too
            var footEl = $("#clone tfoot");
            if(footEl.length){
                footEl.css({
                    visibility:"hidden"
                });
            }
        }
    } 
    else {
        $("#clone").remove();
    }
}
$(window).scroll(moveScroll);
seeit360
la source
Cela fonctionne mieux que la solution d'entropie en ce qui concerne le formatage de la bordure dans l'en-tête. Cependant, dans Firefox actuel (mais pas Chrome), il crée des artefacts visibles de bordure de cellule sous le tableau une fois le défilement commencé.
alanng
2

Voici une solution qui s'appuie sur la réponse acceptée. Il corrige: la largeur des colonnes, le style de tableau correspondant et le défilement du tableau dans un conteneur div.

Usage

Assurez-vous que votre table comporte une <thead>balise, car seul le contenu de la tête sera corrigé.

$("#header-fixed").fixHeader();

JavaSript

//Custom JQuery Plugin
(function ($) {
    $.fn.fixHeader = function () {
        return this.each(function () {
            var $table = $(this);
            var $sp = $table.scrollParent();
            var tableOffset = $table.position().top;
            var $tableFixed = $("<table />")
                .prop('class', $table.prop('class'))
                .css({ position: "fixed", "table-layout": "fixed", display: "none", "margin-top": "0px" });
            $table.before($tableFixed);
            $tableFixed.append($table.find("thead").clone());

            $sp.bind("scroll", function () {
                var offset = $(this).scrollTop();

                if (offset > tableOffset && $tableFixed.is(":hidden")) {
                    $tableFixed.show();
                    var p = $table.position();
                    var offset = $sp.offset();

                    //Set the left and width to match the source table and the top to match the scroll parent
                    $tableFixed.css({ left: p.left + "px", top: (offset ? offset.top : 0) + "px", }).width($table.width());

                    //Set the width of each column to match the source table
                    $.each($table.find('th, td'), function (i, th) {
                        $($tableFixed.find('th, td')[i]).width($(th).width());
                    });

                }
                else if (offset <= tableOffset && !$tableFixed.is(":hidden")) {
                    $tableFixed.hide();
                }
            });
        });
    };
})(jQuery);
Ben Gripka
la source
1
Cela a bien fonctionné pour moi. La seule chose est un problème avec les tableaux qui doivent défiler horizontalement. J'ai fait une mise à jour dans un JSFiddle ici jsfiddle.net/4mgneob1/1 Je soustrais $sp.scrollLeft()ce qui fait défiler le montant de gauche, donc lors du défilement vers le bas, la table fixe est positionnée correctement. Ajout d'une vérification lors du défilement horizontal si la table fixe est visible pour ajuster la position gauche. Un autre problème que je ne pouvais pas résoudre est que lorsque la table passe au-dessus de la fenêtre, la table fixe doit se cacher jusqu'à ce que l'utilisateur revienne en arrière.
Henesnarfel le
1
ObtenirUncaught TypeError: $table.scrollParent is not a function
Karlingen
1

Cela vous aidera à avoir un en-tête fixe qui peut également être défilé horizontalement avec des données.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Shubh</title>



<script type="text/javascript">
    var lastSeen = [ 0, 0 ];
    function checkScroll(div1, div2) {
        if (!div1 || !div2)
            return;
        var control = null;
        if (div1.scrollLeft != lastSeen[0])
            control = div1;
        else if (div2.scrollLeft != lastSeen[1])
            control = div2;
        if (control == null)
            return;
        else
            div1.scrollLeft = div2.scrollLeft = control.scrollLeft;
        lastSeen[0] = div1.scrollLeft;
        lastSeen[1] = div2.scrollLeft;
    }

    window
            .setInterval(
                    "checkScroll(document.getElementById('innertablediv'), document.getElementById('headertable'))",
                    1);
</script>

<style type="text/css">
#full {
    width: 400px;
    height: 300px;
}

#innertablediv {
    height: 200px;
    overflow: auto;
}

#headertable {
    overflow: hidden;
}
</style>
</head>
<body>

    <div id="full">




        <div id="headertable">
            <table border="1" bgcolor="grey" width="150px" id="headertable">
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>

                    <td>&nbsp;&nbsp;&nbsp;</td>
                </tr>

            </table>
        </div>




        <div id="innertablediv">

            <table border="1" id="innertableid">
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>

            </table>
        </div>
    </div>
</body>
</html>
user2669926
la source
Cela vous aidera à avoir un en-tête fixe qui peut également être défilé horizontalement avec des données.
user2669926
1
function fix_table_header_position(){
 var width_list = [];
 $("th").each(function(){
    width_list.push($(this).width());
 });
 $("tr:first").css("position", "absolute");
 $("tr:first").css("z-index", "1000");
 $("th, td").each(function(index){
    $(this).width(width_list[index]);
 });

 $("tr:first").after("<tr height=" + $("tr:first").height() + "></tr>");}

C'est ma solution

Juste nous
la source
1

Un peu tard à la fête, mais voici une implémentation qui fonctionne avec plusieurs tables sur la même page et "jank" gratuitement (en utilisant requestAnimationFrame). De plus, il n'est pas nécessaire de fournir une largeur sur les colonnes. Le défilement horizontal fonctionne également.

Les en-têtes sont définis dans un divafin que vous soyez libre d'y ajouter n'importe quel balisage (comme des boutons), si nécessaire. C'est tout le HTML nécessaire:

<div class="tbl-resp">
  <table id="tbl1" class="tbl-resp__tbl">
     <thead>
      <tr>
        <th>col 1</th>
        <th>col 2</th>
        <th>col 3</th>
      </tr>
    </thead> 
  </table>
</div>

https://jsfiddle.net/lloydleo/bk5pt5gs/

Leo
la source
1

Dans cette solution, l'en-tête fixe est créé dynamiquement, le contenu et le style sont clonés à partir de THEAD

il vous suffit de deux lignes par exemple:

var $myfixedHeader = $("#Ttodo").FixedHeader(); //create fixed header $(window).scroll($myfixedHeader.moveScroll); //bind function to scroll event

Mon plugin jquery FixedHeader et getStyleObject fournis ci-dessous, vous pouvez mettre dans le fichier .js

// JAVASCRIPT



/*
 * getStyleObject Plugin for jQuery JavaScript Library
 * From: http://upshots.org/?p=112
 
Basic usage:
$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}
*/

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            };
            style = window.getComputedStyle(dom, null);
            for(var i = 0, l = style.length; i < l; i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            };
            return returns;
        };
        if(style = dom.currentStyle){
            for(var prop in style){
                returns[prop] = style[prop];
            };
            return returns;
        };
        return this.css();
    }
})(jQuery);



   
//Floating Header of long table  PiotrC
(function ( $ ) {
    var tableTop,tableBottom,ClnH;
    $.fn.FixedHeader = function(){
        tableTop=this.offset().top,
        tableBottom=this.outerHeight()+tableTop;
        //Add Fixed header
        this.after('<table id="fixH"></table>');
        //Clone Header
        ClnH=$("#fixH").html(this.find("thead").clone());
        //set style
        ClnH.css({'position':'fixed', 'top':'0', 'zIndex':'60', 'display':'none',
        'border-collapse': this.css('border-collapse'),
		'border-spacing': this.css('border-spacing'),
        'margin-left': this.css('margin-left'),
        'width': this.css('width')            
        });
        //rewrite style cell of header
        $.each(this.find("thead>tr>th"), function(ind,val){
            $(ClnH.find('tr>th')[ind]).css($(val).getStyleObject());
        });
    return ClnH;}
    
    $.fn.moveScroll=function(){
        var offset = $(window).scrollTop();
        if (offset > tableTop && offset<tableBottom){
            if(ClnH.is(":hidden"))ClnH.show();
            $("#fixH").css('margin-left',"-"+$(window).scrollLeft()+"px");
        }
        else if (offset < tableTop || offset>tableBottom){
            if(!ClnH.is(':hidden'))ClnH.hide();
        }
    };
})( jQuery );





var $myfixedHeader = $("#repTb").FixedHeader();
$(window).scroll($myfixedHeader.moveScroll);
/* CSS - important only NOT transparent background */

#repTB{border-collapse: separate;border-spacing: 0;}

#repTb thead,#fixH thead{background: #e0e0e0 linear-gradient(#d8d8d8 0%, #e0e0e0 25%, #e0e0e0 75%, #d8d8d8 100%) repeat scroll 0 0;border:1px solid #CCCCCC;}

#repTb td{border:1px solid black}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


<h3>example</h3> 
<table id="repTb">
<thead>
<tr><th>Col1</th><th>Column2</th><th>Description</th></tr>
</thead>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
</table>

Piotr C.
la source
1

Créez une table supplémentaire avec le même en-tête que la table principale. Il suffit de mettre la tête dans le nouveau tableau avec une ligne et tous les en-têtes. Positionnez le blanc absolu et le fond. Pour la table principale, placez-le dans un div et utilisez un défilement de hauteur et de débordement. De cette façon, notre nouvelle table surmontera l'en-tête de la table principale et y restera. Entourez tout dans un div. Voici le code approximatif pour le faire.

      <div class="col-sm-8">

        <table id="header-fixed" class="table table-bordered table-hover" style="width: 351px;position: absolute;background: white;">
        <thead>
        <tr>
            <th>Col1</th>
            <th>Col2</th>
            <th>Col3</th>
        </tr>
    </thead>
      </table>


    <div style="height: 300px;overflow-y: scroll;">
          <table id="tableMain" class="table table-bordered table-hover" style="table-layout:fixed;overflow-wrap: break-word;cursor:pointer">
<thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>

                                    </table>
              </div>
        </div>
Novice_JS
la source
1

div.wrapper {
    padding:20px;
}
table.scroll thead {
    width: 100%;
    background: #FC6822;
}
table.scroll thead tr:after {
    content: '';
    overflow-y: scroll;
    visibility: hidden;
}
table.scroll thead th {
    flex: 1 auto;
    display: block;
    color: #fff;
}
table.scroll tbody {
    display: block;
    width: 100%;
    overflow-y: auto;
    height: auto;
    max-height: 200px;
}
table.scroll thead tr,
table.scroll tbody tr {
    display: flex;
}
table.scroll tbody tr td {
    flex: 1 auto;
    word-wrap: break;
}
table.scroll thead tr th,
table.scroll tbody tr td {
    width: 25%;
    padding: 5px;
    text-align-left;
    border-bottom: 1px solid rgba(0,0,0,0.3);
}
<div class="wrapper">
    <table border="0" cellpadding="0" cellspacing="0" class="scroll">
        <thead>
            <tr>
                <th>Name</th>
                <th>Vorname</th>
                <th>Beruf</th>
                <th>Alter</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
        </tbody>
    </table>
</div>

Démo: Démo d'en -tête de table fixe CSS

revilodesign.de
la source
1

Résolvez votre problème avec ceci

tbody {
  display: table-caption;
  height: 200px;
  caption-side: bottom;
  overflow: auto;
}
J Benjamín Samayoa
la source
0

Cela peut être réalisé en utilisant la transformation de propriété de style. Tout ce que vous avez à faire est d'envelopper votre table dans un div avec une hauteur fixe et un débordement réglé sur auto, par exemple:

.tableWrapper {
  overflow: auto;
  height: calc( 100% - 10rem );
}

Et puis vous pouvez y attacher le gestionnaire onscroll, ici vous avez une méthode qui trouve chaque table enveloppée avec <div class="tableWrapper"></div>:

  fixTables () {
    document.querySelectorAll('.tableWrapper').forEach((tableWrapper) => {
      tableWrapper.addEventListener('scroll', () => {
        var translate = 'translate(0,' + tableWrapper.scrollTop + 'px)'
        tableWrapper.querySelector('thead').style.transform = translate
      })
    })
  }

Et voici un exemple de travail de cela en action (j'ai utilisé le bootstrap pour le rendre plus joli): violon

Pour ceux qui souhaitent également prendre en charge IE et Edge, voici l'extrait:

  fixTables () {
    const tableWrappers = document.querySelectorAll('.tableWrapper')
    for (let i = 0, len = tableWrappers.length; i < len; i++) {
      tableWrappers[i].addEventListener('scroll', () => {
        const translate = 'translate(0,' + tableWrappers[i].scrollTop + 'px)'
        const headers = tableWrappers[i].querySelectorAll('thead th')
        for (let i = 0, len = headers.length; i < len; i++) {
          headers[i].style.transform = translate
        }
      })
    }
  }

Dans IE et Edge, le défilement est un peu lent ... mais cela fonctionne

Voici la réponse qui m'aide à découvrir ceci: réponse

Daniel Budzyński
la source
0

J'ai essayé la plupart de ces solutions et j'ai finalement trouvé (IMO) la meilleure solution moderne:

Grilles CSS


Avec les grilles CSS, vous pouvez définir une `` grille '', et vous pouvez enfin créer une belle solution multi-navigateurs, sans javascript, pour une table avec un en-tête fixe et un contenu défilable. La hauteur de la tête peut même être dynamique.

CSS : Afficher sous forme de grille et définir le nombre de template-rows:

.grid {
    display: grid;
    grid-template-rows: 50px auto; // For fixed height header
    grid-template-rows: auto auto; // For dynamic height header
}

HTML : Créez un conteneur de grille et le nombre de défini rows:

<div class="grid">
    <div></div>
    <div></div>
</div>

Voici un exemple de travail:

CSS

body {
  margin: 0px;
  padding: 0px;
  text-align: center;
}

.table {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: 50px auto;
}
.table-heading {
  background-color: #ddd;
}
.table-content {
  overflow-x: hidden;
  overflow-y: scroll;
}

HTML

<html>
    <head>
    </head>
    <body>
        <div class="table">
            <div class="table-heading">
                HEADING
            </div>
            <div class="table-content">
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
            </div>
        </div>
    </body>
</html>
Jeffrey Roosendaal
la source
0

Je l'ai essayé en utilisant la transformation: translate . Bien que cela fonctionne bien dans Firefox et Chrome, il n'y a tout simplement aucune fonction dans IE11. Pas de double barre de défilement. Prend en charge le tableau tfoot et la légende. Javascript pur, pas de jQuery.

http://jsfiddle.net/wbLqzrfb/42/

thead.style.transform="translate(0,"+(dY-top-1)+"px)";
Henrik Haftmann
la source
0

J'ai trouvé une solution sans jquery

HTML

<table class="fixed_header">
  <thead>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
      <th>Col 4</th>
      <th>Col 5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>row 1-0</td>
      <td>row 1-1</td>
      <td>row 1-2</td>
      <td>row 1-3</td>
      <td>row 1-4</td>
    </tr>
    <tr>
      <td>row 2-0</td>
      <td>row 2-1</td>
      <td>row 2-2</td>
      <td>row 2-3</td>
      <td>row 2-4</td>
    </tr>
    <tr>
      <td>row 3-0</td>
      <td>row 3-1</td>
      <td>row 3-2</td>
      <td>row 3-3</td>
      <td>row 3-4</td>
    </tr>
    <tr>
      <td>row 4-0</td>
      <td>row 4-1</td>
      <td>row 4-2</td>
      <td>row 4-3</td>
      <td>row 4-4</td>
    </tr>
    <tr>
      <td>row 5-0</td>
      <td>row 5-1</td>
      <td>row 5-2</td>
      <td>row 5-3</td>
      <td>row 5-4</td>
    </tr>
    <tr>
      <td>row 6-0</td>
      <td>row 6-1</td>
      <td>row 6-2</td>
      <td>row 6-3</td>
      <td>row 6-4</td>
    </tr>
    <tr>
      <td>row 7-0</td>
      <td>row 7-1</td>
      <td>row 7-2</td>
      <td>row 7-3</td>
      <td>row 7-4</td>
    </tr>
  </tbody>
</table>

CSS

.fixed_header{
    width: 400px;
    table-layout: fixed;
    border-collapse: collapse;
}

.fixed_header tbody{
  display:block;
  width: 100%;
  overflow: auto;
  height: 100px;
}

.fixed_header thead tr {
   display: block;
}

.fixed_header thead {
  background: black;
  color:#fff;
}

.fixed_header th, .fixed_header td {
  padding: 5px;
  text-align: left;
  width: 200px;
}

Vous pouvez le voir fonctionner ici: https://jsfiddle.net/lexsoul/fqbsty3h

Source: https://medium.com/@vembarrajan/html-css-tricks-scroll-able-table-body-tbody-d23182ae0fbc

Lexsoul
la source