web-dev-qa-db-fra.com

CSS-Only Scrollable Table avec en-têtes fixes

J'ai une solution grâce à laquelle je peux créer des tableaux déroulants avec en-tête/pied de page fixes à l'aide de jQuery et CSS mineurs - mais je cherche un moyen de faire de cette solution une solution CSS uniquement compatible avec tous les navigateurs.

Pour être clair, ce que je cherche à faire est d’utiliser uniquement une balise table (et ses sous-balises valides, colgroup, col, thead, tbody, tfoot, tr, th, td), mais adoptez un ensemble de règles CSS répondant aux conditions suivantes:

  1. Maintenir l'alignement des colonnes entre les lignes d'en-tête/pied de page/contenu
  2. Laisser l'en-tête/le pied de page rester fixe pendant que le contenu défile verticalement
  3. Ne doit pas nécessiter de jQuery ou autre JavaScript pour fournir la fonctionnalité
  4. Ne doit utiliser que les balises fournies ci-dessus

Cet exemple de code: http://jsfiddle.net/TroyAlford/SNKfd/ montre mon approche actuelle. La plupart du JS est juste pour remplir le tableau avec des valeurs aléatoires, mais la dernière partie est ce qui détermine la possibilité de défilement gauche/droite.

$tbody.bind('scroll', function(ev) {
    var $css = { 'left': -ev.target.scrollLeft };
    $thead.css($css);
    $tfoot.css($css);
});

REMARQUE: L'exemple fourni ne s'affiche pas correctement dans IE et nécessite que jQuery fournisse le défilement horizontal. De toute façon, le défilement horizontal me importe peu, alors ça va si une solution ne le fait pas.

60
Troy Alford

Cette réponse servira d'espace réservé pour position: sticky Non pris en charge et sera mise à jour au fil du temps. Il est actuellement conseillé de ne pas utiliser l'implémentation native de celle-ci dans un environnement de production.

Voir ceci pour le support actuel: https://caniuse.com/#feat=css-sticky


Utilisation de position: sticky

Une autre solution serait d'utiliser position: sticky. comme décrit par le W3C :

Une case collée est positionnée de la même manière qu'une case relativement positionnée, mais le décalage est calculé en référence à l'ancêtre le plus proche avec une case de défilement ou à la fenêtre d'affichage si aucun ancêtre n'a de case de défilement.

Ceci décrit exactement le comportement d'un en-tête statique relatif. Il serait facile d’assigner cela à la balise HTML <thead> Ou à la première balise HTML <tr>, Car elle devrait être prise en charge selon W3C . Cependant, Chrome , IE et Edge ont des problèmes pour attribuer une propriété de position collante à ces balises. Il semble également n'y avoir aucune priorité dans la résolution de ce problème pour le moment.

Ce qui semble fonctionner pour un élément de table est l’affectation de la propriété sticky à une cellule de table. Dans ce cas, les cellules <th>.

Comme une table n'est pas un élément de bloc qui respecte la taille statique que vous lui attribuez, il est préférable d'utiliser un élément wrapper pour définir le défilement-dépassement.

Le code

div {
  display: inline-block;
  height: 150px;
  overflow: auto
}

table th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}


/* == Just general styling, not relevant :) == */

table {
  border-collapse: collapse;
}

th {
  background-color: #1976D2;
  color: #fff;
}

th,
td {
  padding: 1em .5em;
}

table tr {
  color: #212121;
}

table tr:nth-child(odd) {
  background-color: #BBDEFB;
}
<div>
  <table border="0">
    <thead>
      <tr>
        <th>head1</th>
        <th>head2</th>
        <th>head3</th>
        <th>head4</th>
      </tr>
    </thead>
    <tr>
      <td>row 1, cell 1</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
    </tr>
    <tr>
      <td>row 2, cell 1</td>
      <td>row 2, cell 2</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
    </tr>
    <tr>
      <td>row 2, cell 1</td>
      <td>row 2, cell 2</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
    </tr>
    <tr>
      <td>row 2, cell 1</td>
      <td>row 2, cell 2</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
    </tr>
    <tr>
      <td>row 2, cell 1</td>
      <td>row 2, cell 2</td>
      <td>row 1, cell 2</td>
      <td>row 1, cell 2</td>
    </tr>
  </table>
</div>

Dans cet exemple, j'utilise un simple wrapper <div> Pour définir le survol de défilement effectué avec une hauteur statique de 150px. Cela peut bien sûr être n'importe quelle taille. Maintenant que la boîte de défilement a été définie, les éléments collants <th> Seront correspondants "à l'ancêtre le plus proche avec une boîte de défilement", qui est le div-wrapper.


Utilisation de position: sticky polyfill

Les périphériques non pris en charge peuvent utiliser un polyfill, qui implémente le comportement via le code. Un exemple est stickybits , qui ressemble au même comportement que le navigateur implémenté position: sticky.

Exemple avec polyfill: http://jsfiddle.net/7UZA4/6957/

17
nkmol

Surpris, une solution utilisant flexbox n'a pas encore été postée.

Voici ma solution en utilisant display: flex et une utilisation basique de :after (grâce à Luggage ) pour maintenir l’alignement même avec la barre de défilement qui garnit un peu la tbody. Cela a été vérifié dans Chrome 45, Firefox 39 et MS Edge . Il peut être modifié avec des propriétés préfixées pour fonctionner dans IE11, puis dans IE10 avec un CSS hack et le 2012 flexbox .).

Notez que la largeur de la table peut être modifiée. cela fonctionne même à 100% largeur.

Le seul inconvénient est que toutes les cellules du tableau doivent avoir la même largeur. Vous trouverez ci-dessous un exemple clairement conçu, mais qui fonctionne correctement lorsque le contenu des cellules varie (les cellules du tableau ont la même largeur et le même habillage de mot, forçage flexbox pour conserver la même largeur quel que soit le contenu). Ici est un exemple où le contenu de la cellule est différent.

Il suffit d'appliquer le .scroll class à une table que vous voulez faire défiler, et assurez-vous qu'il a un thead:

.scroll {
  border: 0;
  border-collapse: collapse;
}

.scroll tr {
  display: flex;
}

.scroll td {
  padding: 3px;
  flex: 1 auto;
  border: 1px solid #aaa;
  width: 1px;
  Word-wrap: break;
}

.scroll thead tr:after {
  content: '';
  overflow-y: scroll;
  visibility: hidden;
  height: 0;
}

.scroll thead th {
  flex: 1 auto;
  display: block;
  border: 1px solid #000;
}

.scroll tbody {
  display: block;
  width: 100%;
  overflow-y: auto;
  height: 200px;
}
<table class="scroll" width="400px">
  <thead>
    <tr>
      <th>Header</th>
      <th>Header</th>
      <th>Header</th>
      <th>Header</th>
      <th>Header</th>
      <th>Header</th>
    </tr>
  </thead>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
  <tr>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
    <td>Data</td>
  </tr>
</table>
18
Purag

Inspiré par la réponse de @Purag, voici une autre solution flexbox:

/* basic settings */
table { display: flex; flex-direction: column; width: 200px; }
tr { display: flex; }
th:nth-child(1), td:nth-child(1) { flex-basis: 35%; }
th:nth-child(2), td:nth-child(2) { flex-basis: 65%; }
thead, tbody { overflow-y: scroll; }
tbody { height: 100px; }

/* color settings*/
table, th, td { border: 1px solid black; }
tr:nth-child(odd) { background: #EEE; }
tr:nth-child(even) { background: #AAA; }
thead tr:first-child { background: #333; }
th:first-child, td:first-child { background: rgba(200,200,0,0.7); }
th:last-child, td:last-child { background: rgba(255,200,0,0.7); }
<table>
    <thead>
      <tr>
        <th>a
        <th>bbbb
    <tbody>
      <tr>
        <td>fooo vsync dynamic
        <td>bar
      <tr>
        <td>a
        <td>b
      <tr>
        <td>a
        <td>b
      <tr>
        <td>a
        <td>b
      <tr>
        <td>a
        <td>b
      <tr>
        <td>a
        <td>b
      <tr>
        <td>a
        <td>b
  </table>
7
Jan Turoň

Autant que je sache, il n'y a pas de moyen standard d'y parvenir uniquement avec CSS, bien que je pense qu'il devrait l'être. Les navigateurs Mozilla supportaient auparavant les en-têtes fixes avec un corps de défilement, mais ils l'ont supprimé ces dernières années.

Après des recherches un peu sur ce sujet, y compris la recherche de ce poste, un ami vient de développer cette solution pour moi; il utilise Javascript mais pas de bibliothèques pré-programmées, et la seule condition requise pour le balisage HTML est que la table ait un nom d'identifiant. Ensuite, à window.onload, appelez une fonction Javascript pour chaque table en donnant l’identifiant, la hauteur et la largeur. Si Javascript est désactivé sur le navigateur, la totalité de la table est affichée en fonction de son balisage d'origine. Si Javascript est activé, la table est ajustée à la hauteur et à la largeur spécifiées, et les défilements, et s'ils existent, ils sont fixés en haut et en bas.

7
Victoria

J'ai réalisé ceci facilement en utilisant ce code:

Donc, vous avez une structure comme celle-ci:

<table>
<thead><tr></tr></thead>
<tbody><tr></tr></tbody>
</table>

juste coiffer le thead avec:

<style>
thead{ 
    position: -webkit-sticky;
    position: -moz-sticky;
    position: -ms-sticky;
    position: -o-sticky;
    position: sticky;
    top: 0px;
}
</style>

Trois choses à considérer:

Tout d'abord, cette propriété est nouvelle. Il n’est pas du tout supporté, mis à part les versions bêta des navigateurs Webkit. Alors mise en garde formateur. Encore une fois, si vous voulez vraiment que vos utilisateurs bénéficient d’en-têtes collants, optez pour une implémentation javascript.

Deuxièmement, si vous l'utilisez, vous devrez incorporer les préfixes du fournisseur. Peut-être que la position: collante fonctionnera un jour. Pour l'instant, cependant, vous devez utiliser la position: -webkit-sticky (et les autres; regardez le bloc de css plus haut dans ce post).

Troisièmement, il n’existe pas de positionnement par défaut pour le moment, vous devez donc au moins inclure top: 0; dans la même déclaration css que la position: -webkit-sticky. Sinon, il suffit de faire défiler l'écran.

5

Si vous avez la possibilité de donner une largeur fixe aux cellules du tableau (et une hauteur fixe à l'en-tête), vous pouvez utiliser le position: fixed option:

http://jsfiddle.net/thundercracker/ZxPeh/23/

Il vous suffirait de le coller dans un iframe. Vous pourriez aussi avoir le défilement horizontal en donnant au iframe une barre de défilement (je pense).


Éditer 2015

Si vous pouvez vivre avec une définition prédéfinie de la largeur de vos cellules de tableau (en pourcentage), voici une solution un peu plus élégante (uniquement pour CSS):

http://jsfiddle.net/7UBMD/77/

3
Greg Rozmarynowycz

Seulement avec CSS:

[~ # ~] css [~ # ~] :

tr {
  width: 100%;
  display: inline-table;
  table-layout: fixed;
}

table{
 height:300px;              // <-- Select the height of the table
 display: -moz-groupbox;    // Firefox Bad Effect
}
tbody{
  overflow-y: scroll;      
  height: 200px;            //  <-- Select the height of the body
  width: 100%;
  position: absolute;
}

Bootply : http://www.bootply.com/AgI8LpDugl

3
Pimento Web

si cela devient difficile là où toutes les solutions mentionnées ne fonctionnent pas (comme cela a été le cas pour moi), essayez une solution à deux tables, comme je l'expliquais dans cette réponse.

https://stackoverflow.com/a/47722456/6488361

1
Ruto Collins

J'ai eu le même problème et après deux jours de recherches, j'ai trouvé cette solution de Ksesocss qui me convient et qui est peut-être bonne pour vous aussi. Il permet un en-tête fixe et une largeur dynamique et utilise uniquement CSS. Le seul problème est que la source est en espagnol mais vous pouvez y trouver le code html et css.

Voici le lien:

http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html

J'espère que ça aide

1
J Belloch

Je vois que ce fil de discussion est inactif depuis un moment, mais ce sujet m'intéresse et, maintenant, avec certains sélecteurs CSS3, cela est simplement devenu plus facile (et plutôt faisable avec uniquement du CSS).

Cette solution repose sur une hauteur maximale du conteneur de la table. Mais il est supporté aussi longtemps que vous pouvez utiliser le :first-child sélecteur.

Violon ici .

Si quelqu'un peut améliorer cette réponse, faites-le! Je prévois d'utiliser cette solution dans une application commerciale bientôt!

[~ # ~] html [~ # ~]

<div id="con">
<table>
    <thead>
        <tr>
            <th>Header 1</th>
            <th>Header 2</th>
            <th>Header 3</th>
        </tr>
    </thead>        
    <tbody>             
    </tbody>
</table>
</div>

[~ # ~] css [~ # ~]

#con{
    max-height:300px;
    overflow-y:auto;
}
thead tr:first-child {
    background-color:#00f;
    color:#fff;
    position:absolute;
}
tbody tr:first-child td{
    padding-top:28px;
}
1
Blunderfest

Comme j'avais récemment besoin de cela, je vais partager une solution qui utilise 3 tables, mais ne nécessite pas JavaScript.

Le tableau 1 (parent) contient deux lignes. La première ligne contient le tableau 2 (enfant 1) pour les en-têtes de colonne. La deuxième ligne contient le tableau 3 (enfant 2) pour le contenu défilant.

Il faut noter que le childTbl doit être 25px plus court que le parentTbl pour que le curseur apparaisse correctement.

This est la source d'où je viens. Je l'ai rendu compatible avec HTML5 sans les balises déconseillées et le CSS en ligne.

.parentTbl table {
  border-spacing: 0;
  border-collapse: collapse;
  border: 0;
  width: 690px;
}
.childTbl table {
  border-spacing: 0;
  border-collapse: collapse;
  border: 1px solid #d7d7d7;
  width: 665px;
}
.childTbl th,
.childTbl td {
  border: 1px solid #d7d7d7;
}
.scrollData {
  width: 690;
  height: 150px;
  overflow-x: hidden;
}
<div class="parentTbl">
  <table>
    <tr>
      <td>
        <div class="childTbl">
          <table class="childTbl">
            <tr>
              <th>Header 1</th>
              <th>Header 2</th>
              <th>Header 3</th>
              <th>Header 4</th>
              <th>Header 5</th>
              <th>Header 6</th>
            </tr>
          </table>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="scrollData childTbl">
          <table>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
            <tr>
              <td>Table Data 1</td>
              <td>Table Data 2</td>
              <td>Table Data 3</td>
              <td>Table Data 4</td>
              <td>Table Data 5</td>
              <td>Table Data 6</td>
            </tr>
          </table>
        </div>
      </td>
    </tr>
  </table>
</div>

Ceci est fiable sur différents navigateurs, l’inconvénient serait de coder en dur les largeurs de table.

0
silver

J'essayais de le comprendre moi-même récemment et je suis arrivé avec une bonne solution qui fonctionne parfaitement dans mon navigateur (Chrome 51) et supporte les largeurs de colonne dynamiques Je dois mentionner qu'après avoir obtenu ma réponse de manière indépendante, j'ai également trouvé une technique similaire décrite ailleurs sur le Web ...

L'astuce consiste à utiliser deux tables identiques placées l'une sur l'autre. La table inférieure est visible et la table supérieure est invisible pour l'en-tête. La table supérieure a aussi pointer-events: none placé sur le tbody pour que les interactions de la souris touchent la table inférieure. De cette façon, la table inférieure défile sous l'en-tête de la table supérieure.

Pour que tout soit mis en forme et redimensionné correctement (lorsque l'utilisateur ajuste la largeur de l'écran, par exemple), les deux tableaux doivent avoir le même comportement de barre de défilement. Cependant, la barre de défilement de la table supérieure est ignorée grâce au pointer-events: none et peut être rendu invisible avec:

<style>
    .hiddenScrollbar::-webkit-scrollbar {
        background-color: transparent;
    }
</style>

Voici le code complet:

<html>

<head>
  <style>
    td {
      border: 1px solid black; 
      white-space: nowrap;
    }
    th {
      background-color: gray;
      border: 1px solid black;
      white-space: nowrap;
    }
    .hiddenScrollbar::-webkit-scrollbar {
      background-color: transparent;
    }
  </style>
</head>

<body>
  Table test. Use mouse wheel to scroll or scroll to the right to see vertical scroll bar. You can also remove the outermost div if you don't want a horizontal scroll bar.
  <br/>
  <div style="display: inline-block; height: 10em; width: 15em; overflow-x: scroll; overflow-y: hidden">
    <div style="position: relative;">
      <div style="display: inline-block; position: absolute; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
        <table style="border-collapse: collapse;">
          <thead>
            <tr>
              <th>Column 1</th>
              <th>Another Column</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Data 1</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 2</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 3</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 4</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 5</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 6</td>
              <td>12340921375021342354235 very long...</td>
            </tr>
            <tr>
              <td>Data 7</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 8</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 9</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 10</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 11</td>
              <td>123409213750213</td>
            </tr>
            <tr>
              <td>Data 12</td>
              <td>123409213750213</td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="hiddenScrollbar" style="display: inline-block; pointer-events: none; position: relative; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
        <table style="border-collapse: collapse;">
          <thead style="pointer-events: auto">
            <tr>
              <th>Column 1</th>
              <th>Another Column</th>
            </tr>
          </thead>
          <tbody style="visibility: hidden">
            <tr>
              <tr>
                <td>Data 1</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 2</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 3</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 4</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 5</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 6</td>
                <td>12340921375021342354235 very long...</td>
              </tr>
              <tr>
                <td>Data 7</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 8</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 9</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 10</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 11</td>
                <td>123409213750213</td>
              </tr>
              <tr>
                <td>Data 12</td>
                <td>123409213750213</td>
              </tr>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div><br/>
Stuff after table.
</body>

</html>

Mises en garde: Davantage de travail est nécessaire pour prouver que cela fonctionne dans les autres navigateurs. De plus, j’étais plutôt libéral dans le mélange des styles de styles en ligne et de styles. Cependant, je pense que le concept général est le meilleur moyen de le faire, car si le navigateur cible le supporte. Les seuls problèmes de fonctionnalité/d’affichage sont que si vous voulez une barre de défilement horizontale, la barre de défilement verticale peut être défilée (comme indiqué dans l’extrait de code). ) Vous pouvez toujours faire défiler avec la molette de la souris. De plus, vous ne pouvez pas avoir un arrière-plan transparent sur l'en-tête (sinon le tableau ci-dessous serait visible). Enfin, vous avez besoin d’un moyen de générer deux tables identiques. Personnellement, j'utilise react.js et il est facile de le faire avec react, mais php ou une autre génération côté serveur ou javascript fonctionneront également.

0
bruceceng

Une autre implémentation mais sans débordement sur tbody et les colonnes dynamiques. Nécessite JavaScript si. Un conteneur div est utilisé pour héberger les en-têtes de colonnes. Lorsque la table défile devant le port d'affichage, un en-tête fixe apparaît en haut. Si tableau fait défiler horizontalement, l'en-tête fixe défile également.

Les en-têtes de colonnes sont créés en utilisant span éléments avec display: inline-block et une marge négative est utilisée pour faire défiler l'en-tête horizontalement. Également optimisé avec RequestAnimationFrame pour éviter tout jank.

function rAF(scrollLeft) {
  var offsetLeft = 0 - scrollLeft;
  $('.hdr__inner span:first-child').css('margin-left', offsetLeft);
}

https://codepen.io/lloydleo/pen/NRpqEE

0
Leo