523 votes

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

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

vertical scroll inside tbody

HTML:

<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>

CSS:

table {
    width: 100%;
    display:block;
}
thead {
    display: inline-block;
    width: 100%;
    height: 20px;
}
tbody {
    height: 200px;
    display: inline-block;
    width: 100%;
    overflow: auto;
}

Je veux éviter d'ajouter quelques autres div, tout ce que je veux, c'est simple table comme ça, et quand j'ai essayer de changer l'affichage, table-layout, position et beaucoup plus de choses dans le CSS de la table ne fonctionne pas bien avec 100% de largeur seulement avec une largeur fixe en pixels.

769voto

Hashem Qolami Points 22990

Afin de rendre l' <tbody> élément de défilement, nous avons besoin de changer la façon dont il est affiché sur la page c'est à dire à l'aide de display: block; pour l'afficher comme un élément de niveau bloc.

Puisque nous changeons l' display de la propriété de l' tbody, nous devons changer cette propriété pour thead élément comme pour l'empêcher de briser la disposition de table.

Nous avons donc:

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 d'affichage de l' thead et tbody éléments de la ligne du groupe (table-header-group et table-row-group) par défaut.

Une fois que nous modifions que, de l'intérieur, tr éléments de ne pas remplir tout l'espace de leur conteneur.

Afin de corriger cela, nous devons calculer la largeur de l' tbody colonnes et d'appliquer la valeur correspondante à l' thead colonnes via JavaScript.

Automatique De La Largeur Des Colonnes

Voici la version jQuery de 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):

vertical scroll inside tbody

TRAVAIL DE DÉMONSTRATION.

Largeur De Table, Largeur Relative Des Colonnes

Comme l'Affiche Originale de besoin, nous pourrions étendre l' table 100% width de son conteneur, puis à l'aide d'une relative (enPourcentage) width pour chacune des colonnes du tableau.

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

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

Depuis, la table a une (sorte de) fluide de mise en page, nous devons ajuster la largeur de l' thead colonnes lorsque le conteneur est redimensionnée.

Par conséquent, nous devrions définir les colonnes de largeurs une fois que la fenêtre est 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:

Fluid Table with vertical scroll inside tbody

TRAVAIL DE DÉMONSTRATION.


Prise en charge du navigateur et les solutions de rechange

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, il ne veut pas travailler correctement sur IE9 et ci-dessous.

C'est parce que dans un tableau de mise en page, tous les éléments doivent suivre les mêmes propriétés structurelles.

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

Refonte de mise en page via JavaScript

Une approche consiste à redessiner la (toute) la disposition de table. L'utilisation de JavaScript pour créer une nouvelle mise en page à la volée et de la poignée et/ou ajuster les largeurs/hauteurs des cellules de façon dynamique.

Par exemple, regardez les exemples suivants:

Tables gigognes

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

Vérifiez le défilement Vertical des tableaux en CSS Jouer.

Cela fonctionne sur la plupart des navigateurs web. Nous pouvons également faire de la logique ci-dessus de manière dynamique via JavaScript.

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

Puisque le but de l'ajout de la barre de défilement verticale à l' <tbody> est de l'affichage de la table d'en-tête en haut de chaque ligne, on pourrait la position de l' thead élément de séjour fixed en haut de l'écran à la place.

Ici, c'est un Travail de Démonstration de cette approche réalisée par Julien.
Il est promis à un navigateur web de soutien.

Et ici un pur CSS mise en œuvre par Willem Van Bockstal.


Le Pur CSS Solution

Ici, c'est le vieux la réponse. Bien sûr, j'ai ajouté une nouvelle méthode et raffinée, les déclarations CSS.

Tableau à Largeur Fixe

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

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

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 le résultat:

Table with Fixed Width

TRAVAIL DE DÉMONSTRATION.

Table avec 100% de Largeur

Dans cette approche, l' table a une largeur de 100% et pour chaque th et td, la valeur de width de la propriété doit être inférieure à 100% / number of cols.

Aussi, nous avons besoin de réduire la largeur de l' thead de la valeur de la largeur de la verticale de la barre de défilement.

Pour ce faire, nous avons besoin d'utiliser CSS3 calc() fonction, 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 va échouer si le contenu de chaque colonne des sauts de ligne, c'est à dire le contenu de chaque cellule doit être assez court.


Dans la suite, il y a deux exemple simple de pur CSS solution que j'ai créé à l'époque j'ai répondu à cette question.

Voici le jsFiddle Démo v2.

Ancienne version: jsFiddle Démo v1

19voto

gavroche Points 23

Je suis à l'aide de display:block pour thead et tbody. En raison de la largeur de la thead colonnes est différente de la largeur de la tbody colonnes.

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

Pour corriger cela, j'utilise les petits jQuery code mais il peut être fait en JavaScript.

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 mon travail de démonstration: http://jsfiddle.net/gavroche/N7LEF/

Ne fonctionne pas sous IE 8

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);           
  }  
 table {margin:0 auto; border-collapse:separate;}
 thead {background:#CCCCCC;display:block}
 tbody {height:10em;overflow-y:scroll;display:block}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="myTable" border="1">
    <thead>
        <tr>
            <th>A really Very Long Header Text</th>
            <th>Normal Header</th>
            <th>Short</th>            
        </tr>    
    </thead>
    <tbody>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
    </tbody>
</table>

7voto

Mikael Lepistö Points 1040

Je l'ai eu enfin droit à de la pure CSS en suivant ces instructions:

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

La première étape consiste à définir le display: block donc un dépassement de capacité et la hauteur peuvent être appliquées. À partir de là, les lignes de la nécessité d'être en position: relative et d'affichage: volume, de sorte qu'ils vont s'asseoir sur le dessus de défilement .

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

Parce que le est en position relative de 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'un ascenseur est présent navigateurs allouer de l'espace pour elle, donc, l'finit par avoir moins d'espace disponible à l' . Notez le léger désalignement cela crée...

La seule solution qui me vient en tête était de mettre un min-width sur toutes les colonnes à l'exception de 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; }

Tout codepen exemple 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]-->

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X