Tableau HTML avec 100% de largeur, avec défilement vertical à l'intérieur du corps

423

Comment puis-je définir une <table>largeur de 100% et mettre uniquement à l'intérieur du <tbody>défilement vertical pour une certaine hauteur?

défilement vertical à l'intérieur du corps

table {
    width: 100%;
    display:block;
}
thead {
    display: inline-block;
    width: 100%;
    height: 20px;
}
tbody {
    height: 200px;
    display: inline-block;
    width: 100%;
    overflow: auto;
}
  
<table>
  <thead>
    <tr>
    	<th>Head 1</th>
    	<th>Head 2</th>
    	<th>Head 3</th>
    	<th>Head 4</th>
    	<th>Head 5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
    	<td>Content 1</td>
    	<td>Content 2</td>
    	<td>Content 3</td>
    	<td>Content 4</td>
    	<td>Content 5</td>
    </tr>
  </tbody>
</table>

Je veux éviter d'ajouter des div supplémentaires, tout ce que je veux, c'est un simple tableau comme celui-ci et lorsque j'essaie de changer l'affichage table-layout, positionet bien d'autres choses dans le tableau CSS ne fonctionnent pas bien avec une largeur de 100% uniquement avec une largeur fixe en px.

Marko S
la source
Je ne sais pas vraiment ce que vous voulez réaliser. regardez ceci: jsfiddle.net/CrSpu et dites comment vous voulez qu'il se comporte
x4rf41
2
je sais mais regardez .. th et td ne sont pas affichés sur toute la largeur .. postimg.org/image/mgd630y61
Marko S
Connexe: stackoverflow.com/questions/1019938/…
Christophe Roussy

Réponses:

675

Afin de faire <tbody>défiler l'élément, nous devons changer la façon dont il est affiché sur la page, c'est-à-dire utiliser display: block;pour l'afficher en tant qu'élément de niveau bloc.

Puisque nous modifions la displaypropriété de tbody, nous devons également modifier cette propriété pour l' theadélément afin d'éviter de casser la disposition du tableau.

Donc nous avons:

thead, tbody { display: block; }

tbody {
    height: 100px;       /* Just for the demo          */
    overflow-y: auto;    /* Trigger vertical scroll    */
    overflow-x: hidden;  /* Hide the horizontal scroll */
}

Les navigateurs Web affichent les éléments theadet tbodysous forme de groupe de lignes ( table-header-groupet table-row-group) par défaut.

Une fois que nous avons changé cela, les tréléments intérieurs ne remplissent pas tout l'espace de leur conteneur.

Pour résoudre ce problème, nous devons calculer la largeur des tbodycolonnes et appliquer la valeur correspondante aux theadcolonnes via JavaScript.

Colonnes de largeur automatique

Voici la version jQuery de la logique ci-dessus:

// Change the selector if needed
var $table = $('table'),
    $bodyCells = $table.find('tbody tr:first').children(),
    colWidth;

// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
    return $(this).width();
}).get();

// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
    $(v).width(colWidth[i]);
});    

Et voici la sortie (sur Windows 7 Chrome 32) :

défilement vertical à l'intérieur du corps

DÉMO DE TRAVAIL .

Tableau pleine largeur, colonnes de largeur relative

Comme l'affiche originale le nécessitait, nous pourrions étendre le tableà 100% de widthson conteneur, puis utiliser un relatif ( pourcentage ) widthpour chaque colonne du tableau.

table {
    width: 100%; /* Optional */
}

tbody td, thead th {
    width: 20%;  /* Optional */
}

Étant donné que la table a une (sorte de) disposition fluide , nous devons ajuster la largeur des theadcolonnes lorsque le conteneur est redimensionné.

Par conséquent, nous devons définir la largeur des colonnes une fois la fenêtre redimensionnée:

// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
    /* Same as before */ 
}).resize(); // Trigger the resize handler once the script runs

La sortie serait:

Table fluide avec défilement vertical à l'intérieur du corps

DÉMO DE TRAVAIL .


Prise en charge du navigateur et alternatives

J'ai testé les deux méthodes ci-dessus sur Windows 7 via les nouvelles versions des principaux navigateurs Web (y compris IE10 +) et cela a fonctionné.

Cependant, cela ne fonctionne pas correctement sur IE9 et les versions antérieures .

En effet, dans une disposition de table , tous les éléments doivent suivre les mêmes propriétés structurelles.

En utilisant display: block;les éléments <thead>et <tbody>, nous avons rompu la structure de la table.

Refonte de la mise en page via JavaScript

Une approche consiste à repenser la disposition (entière) du tableau. Utiliser JavaScript pour créer une nouvelle mise en page à la volée et gérer et / ou ajuster dynamiquement les largeurs / hauteurs des cellules.

Par exemple, jetez un œil aux exemples suivants:

Tables gigognes

Cette approche utilise deux tables imbriquées avec un div contenant. La première tablen'a qu'une seule cellule qui a un div, et le second tableau est placé à l'intérieur de cet divélément.

Vérifiez les tables de défilement vertical sur CSS Play .

Cela fonctionne sur la plupart des navigateurs Web. Nous pouvons également faire la logique ci-dessus dynamiquement via JavaScript.

Tableau avec en-tête fixe sur défilement

Étant donné que le but d'ajouter une barre de défilement verticale à l' <tbody>affichage de l'en- tête du tableau en haut de chaque ligne, nous pourrions positionner l' theadélément pour qu'il reste fixeden haut de l'écran.

Voici une démonstration de travail de cette approche réalisée par Julien .
Il a un support de navigateur Web prometteur.

Et voici une implémentation CSS pure par Willem Van Bockstal .


La solution Pure CSS

Voici l'ancienne réponse. Bien sûr, j'ai ajouté une nouvelle méthode et affiné les déclarations CSS.

Table à largeur fixe

Dans ce cas, le tabledevrait avoir un fixe width (y compris la somme des largeurs des colonnes et la largeur de la barre de défilement verticale) .

Chaque colonne doit avoir une largeur spécifique et la dernière colonne de l' theadélément a besoin d'une plus grande largeur qui est égale à la largeur des autres + la largeur de la barre de défilement verticale.

Par conséquent, le CSS serait:

table {
    width: 716px; /* 140px * 5 column + 16px scrollbar width */
    border-spacing: 0;
}

tbody, thead tr { display: block; }

tbody {
    height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
}

tbody td, thead th {
    width: 140px;
}

thead th:last-child {
    width: 156px; /* 140px + 16px scrollbar width */
}

Voici la sortie:

Table à largeur fixe

DÉMO DE TRAVAIL .

Table avec 100% de largeur

Dans cette approche, le tablea une largeur de 100%et pour chacun thet td, la valeur de la widthpropriété doit être inférieure à 100% / number of cols.

De plus, nous devons réduire la largeur de theadas comme valeur de la largeur de la barre de défilement verticale.

Pour ce faire, nous devons utiliser la calc()fonction CSS3 , comme suit:

table {
    width: 100%;
    border-spacing: 0;
}

thead, tbody, tr, th, td { display: block; }

thead tr {
    /* fallback */
    width: 97%;
    /* minus scroll bar width */
    width: -webkit-calc(100% - 16px);
    width:    -moz-calc(100% - 16px);
    width:         calc(100% - 16px);
}

tr:after {  /* clearing float */
    content: ' ';
    display: block;
    visibility: hidden;
    clear: both;
}

tbody {
    height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
}

tbody td, thead th {
    width: 19%;  /* 19% is less than (100% / 5 cols) = 20% */
    float: left;
}

Voici la démo en ligne .

Remarque: Cette approche échouera si le contenu de chaque colonne rompt la ligne, c'est -à- dire que le contenu de chaque cellule doit être suffisamment court .


Dans ce qui suit, il existe deux exemples simples de solution CSS pure que j'ai créés au moment où j'ai répondu à cette question.

Voici la démo jsFiddle v2 .

Ancienne version: jsFiddle Demo v1

Hashem Qolami
la source
17
Avec display: blockvous perdez les propriétés de la table comme largeur de colonne partagée entre la tête et le corps. Je sais que vous avez corrigé cela en définissant width: 19.2%mais au cas où nous ne connaissions pas la largeur de chaque colonne à l'avance, cela ne fonctionnera pas.
samb
10
Ce code semble supposer que les cellules du corps seront toujours plus larges que les cellules d'en-tête.
Adam Donahue
2
Ne fonctionne pas quand height: 100%(lorsque vous souhaitez que le tableau se développe en bas de la page).
AlikElzin-kilaka du
2
Cela fonctionne également de manière fantastique avec les ng-repeattables AngularJS . Je ne sais pas pourquoi il y a toutes ces bibliothèques avec des en-têtes de table fixes et quoi pas quand il y a cette solution.
chakeda
2
Vous pouvez améliorer cela un peu plus avec la box-sizingpropriété afin que le fait d'avoir des bordures de deux épaisseurs différentes ne perturbe pas l'alignement de la colonne.
Ricca
89

Dans la solution suivante, la table occupe 100% du conteneur parent, aucune taille absolue requise. C'est du CSS pur, une mise en page flexible est utilisée.

Voici à quoi ça ressemble: entrez la description de l'image ici

Inconvénients possibles:

  • la barre de défilement verticale est toujours visible, qu'elle soit obligatoire ou non;
  • la disposition des tableaux est fixe - les colonnes ne sont pas redimensionnées en fonction de la largeur du contenu (vous pouvez toujours définir la largeur de colonne que vous souhaitez explicitement);
  • il y a une taille absolue - la largeur de la barre de défilement, qui est d'environ 0,9 em pour les navigateurs que j'ai pu vérifier.

HTML (raccourci):

<div class="table-container">
    <table>
        <thead>
            <tr>
                <th>head1</th>
                <th>head2</th>
                <th>head3</th>
                <th>head4</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            ...
        </tbody>
    </table>
</div>

CSS, avec quelques décorations omises pour plus de clarté:

.table-container {
    height: 10em;
}
table {
    display: flex;
    flex-flow: column;
    height: 100%;
    width: 100%;
}
table thead {
    /* head takes the height it requires, 
    and it's not scaled when table is resized */
    flex: 0 0 auto;
    width: calc(100% - 0.9em);
}
table tbody {
    /* body takes all the remaining available space */
    flex: 1 1 auto;
    display: block;
    overflow-y: scroll;
}
table tbody tr {
    width: 100%;
}
table thead, table tbody tr {
    display: table;
    table-layout: fixed;
}

code complet sur jsfiddle

Même code en MOINS pour pouvoir le mélanger:

.table-scrollable() {
  @scrollbar-width: 0.9em;
  display: flex;
  flex-flow: column;

  thead,
  tbody tr {
    display: table;
    table-layout: fixed;
  }

  thead {
    flex: 0 0 auto;
    width: ~"calc(100% - @{scrollbar-width})";
  }

  tbody {
    display: block;
    flex: 1 1 auto;
    overflow-y: scroll;

    tr {
      width: 100%;
    }
  }
}
tsayen
la source
2
Merci pour la solution! Il y avait un léger bug .... vous avez défini la largeur de la tête deux fois, et j'ai trouvé que la soustraction de 1.05em de la largeur s'alignait un peu mieux: jsfiddle.net/xuvsncr2/170
TigerBear
1
qu'en est-il du numéro de contenu du personnage? il gâche lors de l'ajout de caractères ou de mots dans les cellules de ligne
Limon
Je pense que la mise en place d'une politique d'emballage appropriée tddevrait aider
tsayen
Une solution comme celle-ci, mais vous n'avez plus besoin de la largeur de 100%?
Alexandre Pereira Nunes
2
@tsayen Comment l'empêcher de se froisser et de se chevaucher lorsque vous redimensionnez la fenêtre?
clearshot66
31

Dans les navigateurs modernes, vous pouvez simplement utiliser css:

th {
  position: sticky;
  top: 0;
  z-index: 2;
}
Gauss
la source
8
Cette incantation est incomplète ... Envie de poster un exemple, ou du moins d'élaborer?
Liam
fonctionne bien, mais ne s'applique qu'à th. Si nous définissons la position collante sur la tête, cela ne fonctionne pas.
Vishal
La tête fixe devrait s'ajouter au W3C!
sonichy
2
Cette réponse fonctionne lorsque vous envelopper votre <table>avec <div>ce qui a overflow-y: auto;et certains max-height. Par exemple:<div style="overflow-y: auto; max-height: 400px;"><table>...</table></div>
Minwork
A partir de 2020, ce sera la réponse choisie (le long de la mise à jour de @Minwork)
Christophe Vidal
18

J'utilise display:blockpour theadet tbody. Pour cette raison, la largeur des theadcolonnes est différente de la largeur des tbodycolonnes.

table {
    margin:0 auto; 
    border-collapse:collapse;
}
thead {
    background:#CCCCCC;
    display:block
}
tbody {
    height:10em;overflow-y:scroll;
    display:block
}

Pour résoudre ce problème, j'utilise un petit jQuerycode, mais cela ne peut être fait JavaScriptqu'en.

var colNumber=3 //number of table columns    

for (var i=0; i<colNumber; i++) {
  var thWidth=$("#myTable").find("th:eq("+i+")").width();
  var tdWidth=$("#myTable").find("td:eq("+i+")").width();      
  if (thWidth<tdWidth)                    
      $("#myTable").find("th:eq("+i+")").width(tdWidth);
  else
      $("#myTable").find("td:eq("+i+")").width(thWidth);           
}  

Voici ma démo de travail: http://jsfiddle.net/gavroche/N7LEF/

Ne fonctionne pas dans IE 8

gavroche
la source
Il s'agit de la solution la meilleure / la plus simple que j'ai trouvée qui permet des largeurs de colonne non fixes (par exemple le contrôle .NET DataGrid). Pour "production", la colNumbervariable pourrait être remplacée par du code qui itère à travers les cellules réelles trouvées à la place, et notez qu'elle ne fonctionne pas correctement s'il y a des colspans (pourrait également être améliorée dans le code, si nécessaire, mais peu probable sur le type de table susceptible de vouloir cette fonction de défilement).
JonBrave
Cela fonctionne (d'une manière), mais ne résiste pas lorsque la taille de la fenêtre est inférieure à la table (car elle ignore la largeur de la barre de défilement).
Fin du codage
Oui, l'en-tête et les cellules ne correspondent plus si la largeur de votre table est limitée à une largeur définie
Craig
meilleure réponse ici, le plus simple aussi
Charles Okwuagwu
18

CSS uniquement

pour Chrome, Firefox, Edge (et autres navigateurs à feuilles persistantes )

Simplement position: sticky; top: 0;vos théléments:

/* Fix table head */
.tableFixHead    { overflow-y: auto; height: 100px; }
.tableFixHead th { position: sticky; top: 0; }

/* Just common table stuff. */
table  { border-collapse: collapse; width: 100%; }
th, td { padding: 8px 16px; }
th     { background:#eee; }
<div class="tableFixHead">
  <table>
    <thead>
      <tr><th>TH 1</th><th>TH 2</th></tr>
    </thead>
    <tbody>
      <tr><td>A1</td><td>A2</td></tr>
      <tr><td>B1</td><td>B2</td></tr>
      <tr><td>C1</td><td>C2</td></tr>
      <tr><td>D1</td><td>D2</td></tr>
      <tr><td>E1</td><td>E2</td></tr>
    </tbody>
  </table>
</div>

PS: si vous avez besoin de bordures pour les éléments TH, th {box-shadow: 1px 1px 0 #000; border-top: 0;}cela vous aidera (car les bordures par défaut ne sont pas peintes correctement lors du défilement).

Pour une variante de ce qui précède qui utilise juste un peu de JS afin de s'adapter à IE11, voir cette réponse https://stackoverflow.com/a/47923622/383904

Roko C. Buljan
la source
Si vous avez des bordures pour les éléments, utiliser "border-collapse: collapse" collera la bordure au corps plutôt qu'à l'en-tête. Pour éviter ce problème, vous devez utiliser "border-collapse: distinct". Voir stackoverflow.com/a/53559396
mrod
@mrod lors de l'utilisation, separatevous ajoutez de l'huile au feu. jsfiddle.net/RokoCB/o0zL4xyw et voir une solution ICI: ajoutez des bordures au TH fixe - Je suis le bienvenu pour des suggestions OFC si j'ai raté quelque chose.
Roko C. Buljan
11

Créez deux tables l'une après l'autre, placez la deuxième table dans un div de hauteur fixe et définissez la propriété overflow sur auto. Gardez également tous les td à l'intérieur de la tête dans la deuxième table vides.

<div>
    <table>
        <thead>
            <tr>
                <th>Head 1</th>
                <th>Head 2</th>
                <th>Head 3</th>
                <th>Head 4</th>
                <th>Head 5</th>
            </tr>
        </thead>
    </table>
</div>

<div style="max-height:500px;overflow:auto;">
    <table>
        <thead>
            <tr>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
            </tr>
        </thead>
        <tbody>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        </tbody>
    </table>    
</div>
Sushil Kumar
la source
8
Dans ce cas, les secondes colonnes du tableau ne peuvent pas suivre la largeur du premier tableau.
kat1330
2
Pas bon! Vous perdez la synchronisation de largeur pour les colonnes sur deux tables.
Zafar
1
pour compléter cette solution, nous devons ajouter le script @Hashem Qolami ( décrit ci-dessus ) pour synchroniser la largeur des colonnes d'en-tête
Elhay Avichzer
6

Je l'ai finalement bien compris avec du CSS pur en suivant ces instructions:

http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/

La première étape consiste à définir le <tbody>bloc à afficher pour qu'un débordement et une hauteur puissent être appliqués. À partir de là, les lignes dans le <thead>besoin doivent être définies sur position: relative et display: block afin qu'elles se placent au-dessus du maintenant défilable <tbody>.

tbody, thead { display: block; overflow-y: auto; }

Parce que le <thead>est relativement positionné, chaque cellule du tableau a besoin d'une largeur explicite

td:nth-child(1), th:nth-child(1) { width: 100px; }
td:nth-child(2), th:nth-child(2) { width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }

Mais malheureusement, cela ne suffit pas. Lorsqu'une barre de défilement est présente, les navigateurs lui allouent de l'espace, donc, <tbody>finit par avoir moins d'espace disponible que le <thead>. Remarquez le léger désalignement que cela crée ...

La seule solution de contournement que j'ai pu trouver était de définir une largeur minimale sur toutes les colonnes sauf la dernière.

td:nth-child(1), th:nth-child(1) { min-width: 100px; }
td:nth-child(2), th:nth-child(2) { min-width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }

Exemple de codepen entier ci-dessous:

CSS:

.fixed_headers {
  width: 750px;
  table-layout: fixed;
  border-collapse: collapse;
}
.fixed_headers th {
  text-decoration: underline;
}
.fixed_headers th,
.fixed_headers td {
  padding: 5px;
  text-align: left;
}
.fixed_headers td:nth-child(1),
.fixed_headers th:nth-child(1) {
  min-width: 200px;
}
.fixed_headers td:nth-child(2),
.fixed_headers th:nth-child(2) {
  min-width: 200px;
}
.fixed_headers td:nth-child(3),
.fixed_headers th:nth-child(3) {
  width: 350px;
}
.fixed_headers thead {
  background-color: #333333;
  color: #fdfdfd;
}
.fixed_headers thead tr {
  display: block;
  position: relative;
}
.fixed_headers tbody {
  display: block;
  overflow: auto;
  width: 100%;
  height: 300px;
}
.fixed_headers tbody tr:nth-child(even) {
  background-color: #dddddd;
}
.old_ie_wrapper {
  height: 300px;
  width: 750px;
  overflow-x: hidden;
  overflow-y: auto;
}
.old_ie_wrapper tbody {
  height: auto;
}

Html:

<!-- IE < 10 does not like giving a tbody a height.  The workaround here applies the scrolling to a wrapped <div>. -->
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->

<table class="fixed_headers">
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Plum</td>
      <td>Purple</td>
      <td>These are Purple</td>
    </tr>
    <tr>
      <td>Watermelon</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Tomato</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cherry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cantelope</td>
      <td>Orange</td>
      <td>These are orange inside.</td>
    </tr>
    <tr>
      <td>Honeydew</td>
      <td>Green</td>
      <td>These are green inside.</td>
    </tr>
    <tr>
      <td>Papaya</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Raspberry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
      <td>These are blue.</td>
    </tr>
    <tr>
      <td>Mango</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Passion Fruit</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

<!--[if lte IE 9]>
</div>
<!--<![endif]-->

EDIT: Solution alternative pour une largeur de table de 100% (ci-dessus est en fait pour une largeur fixe et n'a pas répondu à la question):

HTML:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

CSS:

table {
  width: 100%;
  text-align: left;
  min-width: 610px;
}
tr {
  height: 30px;
  padding-top: 10px
}
tbody { 
  height: 150px; 
  overflow-y: auto;
  overflow-x: hidden;
}
th,td,tr,thead,tbody { display: block; }
td,th { float: left; }
td:nth-child(1),
th:nth-child(1) {
  width: 20%;
}
td:nth-child(2),
th:nth-child(2) {
  width: 20%;
  float: left;
}
td:nth-child(3),
th:nth-child(3) {
  width: 59%;
  float: left;
}
/* some colors */
thead {
  background-color: #333333;
  color: #fdfdfd;
}
table tbody tr:nth-child(even) {
  background-color: #dddddd;
}

Démo: http://codepen.io/anon/pen/bNJeLO

Mikael Lepistö
la source
1
La question voulait spécifiquement une table de 100% de largeur, ce qui est la seule chose que l'exemple auquel vous avez fait référence ne fait pas .
Fin du codage
@TrueBlueAussie Bonne prise: D Ajout d'une solution alternative pour 100% de largeur.
Mikael Lepistö
vous ne considérez pas la longitude du contenu de la ligne de cellule
Limon
2

Solution de contournement CSS pour forcer les colonnes à s'afficher correctement avec un corps de bloc

Cette solution nécessite toujours que les thlargeurs soient calculées et définies par jQuery

table.scroll tbody,
table.scroll thead { display: block; }

table.scroll tbody {
    overflow-y: auto;
    overflow-x: hidden;
    max-height: 300px;
}

table.scroll tr {
    display: flex;
}

table.scroll tr > td {
    flex-grow: 1;
    flex-basis: 0;
}

Et le Jquery / Javascript

var $table = $('#the_table_element'),
    $bodyCells = $table.find('tbody tr:first').children(),
    colWidth;

$table.addClass('scroll');

// Adjust the width of thead cells when window resizes
$(window).resize(function () {

    // Get the tbody columns width array
    colWidth = $bodyCells.map(function () {
        return $(this).width();
    }).get();

    // Set the width of thead columns
    $table.find('thead tr').children().each(function (i, v) {
        $(v).width(colWidth[i]);
    });

}).resize(); // Trigger resize handler
Emmanuel
la source
@Craig en 2019, c'est très bien de ne pas se soucier du tout d'IE.
Automagisch
2

essayez l'approche ci-dessous, très simple, facile à mettre en œuvre

Ci-dessous le lien jsfiddle

http://jsfiddle.net/v2t2k8ke/2/

HTML:

<table border='1' id='tbl_cnt'>
<thead><tr></tr></thead><tbody></tbody>

CSS:

 #tbl_cnt{
 border-collapse: collapse; width: 100%;word-break:break-all;
 }
 #tbl_cnt thead, #tbl_cnt tbody{
 display: block;
 }
 #tbl_cnt thead tr{
 background-color: #8C8787; text-align: center;width:100%;display:block;
 }
 #tbl_cnt tbody {
 height: 100px;overflow-y: auto;overflow-x: hidden;
 }

Jquery:

 var data = [
    {
    "status":"moving","vehno":"tr544","loc":"bng","dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che", "dri":"ttt"
    },{    "status":"idle","vehno":"yy5499999999999994","loc":"bng","dri":"ttt"
    },{
    "status":"moving","vehno":"tr544","loc":"bng", "dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che","dri":"ttt"
    },{
    "status":"idle","vehno":"yy544","loc":"bng","dri":"ttt"
    }
    ];
   var sth = '';
   $.each(data[0], function (key, value) {
     sth += '<td>' + key + '</td>';
   });
   var stb = '';        
   $.each(data, function (key, value) {
       stb += '<tr>';
       $.each(value, function (key, value) {
       stb += '<td>' + value + '</td>';
       });
       stb += '</tr>';
    });
      $('#tbl_cnt thead tr').append(sth);
      $('#tbl_cnt tbody').append(stb);
      setTimeout(function () {
      var col_cnt=0 
      $.each(data[0], function (key, value) {col_cnt++;});    
      $('#tbl_cnt thead tr').css('width', ($("#tbl_cnt tbody") [0].scrollWidth)+ 'px');
      $('#tbl_cnt thead tr td,#tbl_cnt tbody tr td').css('width',  ($('#tbl_cnt thead tr ').width()/Number(col_cnt)) + 'px');}, 100)
Nandha
la source
2
Cette solution ne résiste pas à une fenêtre plus étroite que la largeur de la table. Il devrait permettre le défilement horizontal lorsque cela se produit. De plus, les titres ne s'alignent pas exactement avec les cellules de données (Chrome).
Fin du codage
Cela ne fonctionne pas de nos jours
MrHIDEn
2

Ajouter une largeur fixe à td, th après que le bloc d'affichage tbody & thead fonctionne parfaitement et nous pouvons également utiliser le plugin slimscroll pour rendre la barre de défilement belle.

entrez la description de l'image ici

<!DOCTYPE html>
<html>

<head>
    <title> Scrollable table </title>
    <style>
        body {
            font-family: sans-serif;
            font-size: 0.9em;
        }
        table {
            border-collapse: collapse;
            border-bottom: 1px solid #ddd;
        }
        thead {
            background-color: #333;
            color: #fff;
        }
        thead,tbody {
            display: block;
        }
        th,td {
            padding: 8px 10px;
            border: 1px solid #ddd;
            width: 117px;
            box-sizing: border-box;
        }
        tbody {
            height: 160px;
            overflow-y: scroll
        }
    </style>
</head>

<body>

    <table class="example-table">
        <thead>
            <tr>
                <th> Header 1 </th>
                <th> Header 2 </th>
                <th> Header 3 </th>
                <th> Header 4 </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td> Row 1- Col 1 </td>
                <td> Row 1- Col 2 </td>
                <td> Row 1- Col 3 </td>
                <td> Row 1- Col 4 </td>
            </tr>
            <tr>
                <td> Row 2- Col 1 </td>
                <td> Row 2- Col 2 </td>
                <td> Row 2- Col 3 </td>
                <td> Row 2- Col 4 </td>
            </tr>
            <tr>
                <td> Row 3- Col 1 </td>
                <td> Row 3- Col 2 </td>
                <td> Row 3- Col 3 </td>
                <td> Row 3- Col 4 </td>
            </tr>
            <tr>
                <td> Row 4- Col 1 </td>
                <td> Row 4- Col 2 </td>
                <td> Row 4- Col 3 </td>
                <td> Row 4- Col 4 </td>
            </tr>
            <tr>
                <td> Row 5- Col 1 </td>
                <td> Row 5- Col 2 </td>
                <td> Row 5- Col 3 </td>
                <td> Row 5- Col 4 </td>
            </tr>
            <tr>
                <td> Row 6- Col 1 </td>
                <td> Row 6- Col 2 </td>
                <td> Row 6- Col 3 </td>
                <td> Row 6- Col 4 </td>
            </tr>
            <tr>
                <td> Row 7- Col 1 </td>
                <td> Row 7- Col 2 </td>
                <td> Row 7- Col 3 </td>
                <td> Row 7- Col 4 </td>
            </tr>
            <tr>
                <td> Row 8- Col 1 </td>
                <td> Row 8- Col 2 </td>
                <td> Row 8- Col 3 </td>
                <td> Row 8- Col 4 </td>
            </tr>
            <tr>
                <td> Row 9- Col 1 </td>
                <td> Row 9- Col 2 </td>
                <td> Row 9- Col 3 </td>
                <td> Row 9- Col 4 </td>
            </tr>
            <tr>
                <td> Row 10- Col 1 </td>
                <td> Row 10- Col 2 </td>
                <td> Row 10- Col 3 </td>
                <td> Row 10- Col 4 </td>
            </tr>
            <tr>
                <td> Row 11- Col 1 </td>
                <td> Row 11- Col 2 </td>
                <td> Row 11- Col 3 </td>
                <td> Row 11- Col 4 </td>
            </tr>
            <tr>
                <td> Row 12- Col 1 </td>
                <td> Row 12- Col 2 </td>
                <td> Row 12- Col 3 </td>
                <td> Row 12- Col 4 </td>
            </tr>
            <tr>
                <td> Row 13- Col 1 </td>
                <td> Row 13- Col 2 </td>
                <td> Row 13- Col 3 </td>
                <td> Row 13- Col 4 </td>
            </tr>
            <tr>
                <td> Row 14- Col 1 </td>
                <td> Row 14- Col 2 </td>
                <td> Row 14- Col 3 </td>
                <td> Row 14- Col 4 </td>
            </tr>
            <tr>
                <td> Row 15- Col 1 </td>
                <td> Row 15- Col 2 </td>
                <td> Row 15- Col 3 </td>
                <td> Row 15- Col 4 </td>
            </tr>
            <tr>
                <td> Row 16- Col 1 </td>
                <td> Row 16- Col 2 </td>
                <td> Row 16- Col 3 </td>
                <td> Row 16- Col 4 </td>
            </tr>
        </tbody>
    </table>


    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-slimScroll/1.3.8/jquery.slimscroll.min.js"></script>
    <script>
        $('.example-table tbody').slimscroll({
            height: '160px',
            alwaysVisible: true,
            color: '#333'
        })
    </script>
</body>

</html>

codegeek
la source
1

Voici le code qui fonctionne pour moi pour créer une tête collante sur une table avec un corps défilant:

table ,tr td{
    border:1px solid red
}
tbody {
    display:block;
    height:50px;
    overflow:auto;
}
thead, tbody tr {
    display:table;
    width:100%;
    table-layout:fixed;/* even columns width , fix width of table too*/
}
thead {
    width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
    width:400px;
}
Max Alexander Hanna
la source
1

Pour utiliser "overflow: scroll", vous devez définir "display: block" sur la tête et le corps. Et cela gâche la largeur des colonnes entre eux. Mais ensuite, vous pouvez cloner la ligne de tête avec Javascript et la coller dans le corps comme une ligne cachée pour conserver les largeurs de col exactes.

$('.myTable thead > tr').clone().appendTo('.myTable tbody').addClass('hidden-to-set-col-widths');

http://jsfiddle.net/Julesezaar/mup0c5hk/

<table class="myTable">
    <thead>
        <tr>
            <td>Problem</td>
            <td>Solution</td>
            <td>blah</td>
            <td>derp</td>
        </tr>
    </thead>
    <tbody></tbody>
</table>
<p>
  Some text to here
</p>

Le css:

table {
  background-color: #aaa;
  width: 100%;
}

thead,
tbody {
  display: block; // Necessary to use overflow: scroll
}

tbody {
  background-color: #ddd;
  height: 150px;
  overflow-y: scroll;
}

tbody tr.hidden-to-set-col-widths,
tbody tr.hidden-to-set-col-widths td {
  visibility: hidden;
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}

td {
  padding: 3px 10px;
}
Julesezaar
la source
0

Essayez ce jsfiddle . Ceci utilise jQuery et fait à partir de la réponse de Hashem Qolami. Dans un premier temps, créez un tableau régulier puis faites-le défiler.

const makeScrollableTable = function (tableSelector, tbodyHeight) {
  let $table = $(tableSelector);
  let $bodyCells = $table.find('tbody tr:first').children();
  let $headCells = $table.find('thead tr:first').children();
  let headColWidth = 0;
  let bodyColWidth = 0;

  headColWidth = $headCells.map(function () {
    return $(this).outerWidth();
  }).get();
  bodyColWidth = $bodyCells.map(function () {
    return $(this).outerWidth();
  }).get();

  $table.find('thead tr').children().each(function (i, v) {
    $(v).css("width", headColWidth[i]+"px");
    $(v).css("min-width", headColWidth[i]+"px");
    $(v).css("max-width", headColWidth[i]+"px");
  });
  $table.find('tbody tr').children().each(function (i, v) {
    $(v).css("width", bodyColWidth[i]+"px");
    $(v).css("min-width", bodyColWidth[i]+"px");
    $(v).css("max-width", bodyColWidth[i]+"px");
  });

  $table.find('thead').css("display", "block");
  $table.find('tbody').css("display", "block");

  $table.find('tbody').css("height", tbodyHeight+"px");
  $table.find('tbody').css("overflow-y", "auto");
  $table.find('tbody').css("overflow-x", "hidden");

};
le chat
la source