Passer aux structures CSS ne veut pas dire la fin de la table HTML, bien au contraire. Si le CSS1 en a séduit plus d’un, moi le premier, autant fut grande la déception de comprendre qu’il ne remplaçait pas la saudite table HTML. La table HTML, destinée à contenir des données tabulaires, n’est pas vraiment optimisée pour construire la structure d’une page web. Et ce bien que la grande majorité des sites Web l’utilise encore, voilà le discours toujours d’actualité. Effectivement je suis de ceux qui ont toujours trouvé les tables HTML mal adaptée, ne serait-ce que sémantiquement. Mais de là en faire une phobie, un enfer! Voyons si vraiment c’est le cas. Selon deux préceptes. Le premier est l’optimalisation, tant d’utilisation, de gestion que de vitesse d’exécution et de chargement. L’autre, la compatibilité, bien sûr.
Les avantages de la Table HTML
Centrage vertical
Vous vous êtes déjà probablement arraché les cheveux à essayer de centrer verticalement le contenu d’un élément de type « bloc ». Alors qu’il suffit d’utiliser une cellule d’une table HTML pour régler le problème. Au fil des années on a utilisé moult techniques plus ou moins logique. Avec conteneur, marge et la propriété vertical-align:middle
, ou line-height: 200px;
par exemple.
Fausse colonne
Un autre problème récurrent est une colonne qui sort de la structure ou encore qui n’occupe pas la hauteur totale de la structure. Une couleur de fond par exemple qui ne se rend pas en bas de la page. Alors qu’on sait tous que chaque colonne d’une table HTML ne sort pas de la structure tout en occupant l’ensemble de l’espace. Dans ce cas, le truc était d’utiliser un pattern de fond qui simule la colonne ou mieux encore, la propriété overflow:hidden
. On ne peut pas dire que la logique était au rendez-vous encore une fois.
Éléments colspan et rowspan
Le nombre de colonnes, ou lignes, occupées par une cellule. Quoi dire de plus, rien ne permet encore de gérer aussi facilement cet aspect pourtant indispensable de la table HTML, pas même le CSS3. Déjà de loin ce qui a de plus complexe à saisir en HTML pour le néophyte, imaginer y ajouter des notions CSS3!
Sémantique
Un autre avantage de la table HTML est la sémantique des balises, enfin pour un anglais ; -) table
, caption
, thead
, foot
, tbody
, col
, colgroup
, tr
(table row), td
(table data) et th
(table header). Clair et net, en autant qu’il s’agisse d’un tableau de données. Car dans une structure HTML on conviendra que ce n’est plus vraiment le cas. Alors qu’un DIV
non seulement ne dit rien mais en plus il faut absolument créer une feuille de style pour l’organiser un tant soit peu.
Compatibilité
Malgré tout, le tableau est là depuis que le HTML existe. Tous les navigateurs, même Netscape ont été créé après le HTML. Il reste donc à ce jour ce qu’il y a de plus compatible.
Le véritable désavantage du tableau :
Pour bien comprendre il faut savoir comment le « document objet-modèle » (DOM) fonctionne et surtout comment le navigateur doit lire plusieurs fois le code source pour bâtir le DOM. Premièrement le navigateur s’assure qu’il n’y a pas d’erreur. Il va par exemple ajouter les balises manquantes dans le DOM, si vous omettez le balise tbody
dans une table... C’est pour cette raison que le DOM n’est pas le code source d’ailleurs. Ensuite, il devra estimer l’espace qu’occupera la table HTML. C’est-à-dire qu’il devra lire une première fois la table pour définir sa structure et une seconde fois pour y intégrer le contenu. Et ce à chaque fois.
Le pire c’est que l’internaute devra attendre que l’ensemble du tableau soit traité, jusqu’à la dernière ligne, avant de l’afficher. C’est là le pire défaut de la table HTML. Comparativement, un élément de type bloc comme un DIV
est plus rapide. L’ironie est que les machines et les connexions d’aujourd’hui sont de loin supérieures. Bon on a 2, 3 interceptions, sécurité nationale obligent, mais dans l’ensemble tout va beaucoup plus vite. Ça reste toute foi pour moi une préoccupation sine qua non. « Keep it Simple, Stupid ».
Ce qu’on ne dit pas toujours
Vous avez sans doute rencontré, ici et là, la propriété CSS2 table-layout: fixed;
. Il existe plusieurs méthodes ou algorithmes pour traiter une table HTML. Laisser à la discrétion du navigateur, c’est généralement par défaut automatique
. Alors que table-layout: fixed;
force le navigateur à estimer la table à partir de la première ligne du tableau (ou l’entête) uniquement. Et ce sans devoir lire l’ensemble du tableau.
Il suffit donc d’ajouter cette propriété à vos tableaux HTML pour mettre au rancart un des ses défauts historique!
<style> .tableau { table-layout: fixed; } </style> <table class="tableau"> <caption>Tableau HTML fixe</caption> <thead> <tr> <th>1</th> <th>2</th> <th>3</th> </tr> </thead> <tfoot> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> </tfoot> <tbody> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> </tbody> </table>
Enfin, la table HTML reste une interprétation récurrente que le navigateur doit charger à chaque fois. La feuille de styles à nettement l’avantage d’être entièrement en mémoire cache.
Propriétés CSS2.1
C’est alors que la W3C arrive avec son tableau CSS. Tout d’abord incompatible avec Internet Explorer de Microsoft, il a fallu attendre IE8 avant d’avoir un support adéquat. Mais aujourd’hui, on peut dire que c’est chose du passé car la majorité des navigateurs supportent la table CSS. Firefox 2, Safari 6, Opera 9.5, Google Chrome 25, Internet Explorer 8.
table { display: table } tr { display: table-row } thead { display: table-header-group } tbody { display: table-row-group } tfoot { display: table-footer-group } col { display: table-column } colgroup { display: table-column-group } td, th { display: table-cell } caption { display: table-caption }
Voilà qui est bien beau, c’est en fait une table HTML, en CSS. Sans son caractère sémantique! Mais ça reste la même saudite affaire! On peut faire réagir un élément DIV
comme une table HTML en empruntant ses caractéristiques! Ainsi, au lieu du non sens overflow: hidden;
il y a la propriété display: table-cell
pour avoir une colonne qui va jusqu’en bas. Un height:#100%;
naturel.
Ou encore, au lieu du vertival-align:middle;
, utilisez display: table-cell;
et voilà, comme disent les anglais! On peut même aller jusqu’à reproduire carrément un tableau HTML.
Exemple fluide de structure en trois colonnes.
Contrairement à l’exemple structure HTML5 en colonnes CSS, fluide et adaptative. en pure CSS3, voiçi un exemple simple avec display: table;
.
<style> body, html { height:100%;padding:0;margin:0; } main { display: table; background-color: #d6d3ce; height:100%; width:100%; } aside {width: 20%; display: table-cell; } .ligne { display: table-row; } .gauche { background-color: #c6c3bd; padding: 1em;} .droite { background-color: #c6c3bd; padding: 1em;} .corps { padding: 1em; } </style> <main> <section class="ligne"> <aside class="gauche"> <p>Colonne de gauche</p> </aside> <section class="corps"> <p>Corps du document</p> </section> <aside class="droite"> <p>Colonne de droite</p> </aside> </section> </main>
Vraiment optimisé!
En observant le comportement de la propriété caption-side: bottom;
j’en doute fortement. Je n’ai encore rien trouvé à ce propos mais à mon avis le navigateur doit aussi lire deux fois le code pour savoir où placer la légende. Dans cet exemple :
body { display: table; caption-side: top; } [role="navigation"] { display: table-caption; }
C’est un super truc pour afficher le menu, normalement en haut du code, en bas de la page dans le cas d’un mobile. Mais l’ensemble du document est géré comme une table. Le navigateur doit forcément estimer l’ensemble de la page avant d’y placer le menu? J’y ajouterais déjà un table-layout: fixed;
. Ça reste un mystère pour moi à l’heure d’écrire ces lignes. Mais d’ici à percer le secret, j’éviterais d’utiliser le display: table;
dans la structure globale du site. Et pour ce cas précis, j’opterais pour deux menus, c’est à dire des éléments cachés à l’aide du « @media screen ».
Liste à puces horizontales
Voilà un exemple des plus éloquents. D’autant qu’il se limite à un espace restreint contrairement à la structure globale d’une page Web. Pourquoi utilise ton une liste à puces pour faire un menu? Pourtant ça n’a rien à voir! Parce que c’est simple, loin de la complexité d’un tableau HTML.
Chose que la solution display: table
fait à merveille avec une sémantique tout à fait logique! C’est d’ailleurs la meilleur solution que j’utilise dorénavant, ici avec un affichage adaptatif :
<style> /* Optionnel : style des boutons */ body {margin:0;} [role="navigation"] div a { background-color:#c6c3bd; color:#000000; text-decoration:none; display:block; padding: 1rem 1rem; } [role="navigation"] div a:hover { background-color:#5d625c; color:#ffffff; } @media screen and (min-width: 30em) { [role="navigation"] { display: table; table-layout: fixed; width:100%; background-color:#5d625c; } [role="navigation"] div { display: table-cell; } [role="navigation"] div a { text-align:center; } } </style> <nav role="navigation"> <div><a href="#">Menu 1</a></div> <div><a href="#">Menu 2</a></div> <div><a href="#">Menu 3</a></div> </nav>
N’est-ce pas simple? Davantage qu’une table HTML et même qu’une lite à puce?
Tableau en pure CSS
C’est en fait comme un système de grille sans alignement à gauche (float:right
) et sans « clearing floats » clear:both;
. Plus simple mais ce tableau CSS est exactement comme la table HTML :
<style> .tableau { display: table } .ligne { display: table-row } .tete { display: table-header-group } .corp { display: table-row-group } .pied { display: table-footer-group } .col { display: table-column } .colgroupe { display: table-column-group } .cellule { display: table-cell } .legende { display: table-caption } </style> <section class="tableau"> <div class="legende">Tableau CSS</div> <header class="tete"> <div class="cellule">Col 1</div> <div class="cellule">Col 2</div> <div class="cellule">Col 3</div> </header> <footer class="pied"> <div class="pied">Pied 1</div> <div class="pied">Pied 2</div> <div class="pied">Pied 3</div> </footer> <div class="corp"> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> </div> </section>
Avec un peu de style
<style> .tableau {display: table;border-spacing: 0.5rem;border-collapse: collapse;} .cellule {display: table-cell;padding: 0.5rem; border: 1px solid #999;} .ligne {display: table-row;} /* Quelques sélecteurs */ .ligne:nth-child(odd) {background: #e5f1f4;} .ligne:nth-child(even) {background: #f8fbfc;} .ligne:hover {background: #ecfbd4;cursor:pointer;} .col {display: table-column;} .corp {display: table-row-group} .colgroupe {display: table-column-group;} .pied {display: table-footer-group;font-weight:bold;background-color:#eee;} .tete {background-color:#4a98af;color:#ffffff;display: table-header-group;font-weight:bold;text-align:center;} .legende {display: table-caption;caption-side: top;background-color:#eee;} </style> <section class="tableau"> <div class="colgroupe"> <div class="col"></div> <div class="col"></div> </div> <div class="legende">Tableau CSS</div> <header class="tete"> <div class="cellule">Col 1</div> <div class="cellule">Col 2</div> <div class="cellule">Col 3</div> </header> <footer class="pied"> <div class="cellule">Pied</div> </footer> <div class="corp"> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> <div class="ligne"> <div class="cellule">1</div> <div class="cellule">2</div> <div class="cellule">3</div> </div> </div> </section>
Exemple :
En colonnes CSS3
Notez que depuis le CSS3 il existe aussi la nouvelle propriété columns
que je ne traite pas ici. Cette propriété permet aussi la répartition sur plusieurs colonnes cette fois. Avec la propriété column-span: all;
. Mais non seulement ça ne remplace pas du tout le colspan
d’une table mais en plus la propriété n’est pas encore supporté. Disons que c’est un début...
<style> .trois-colonnes { -webkit-columns: 3; -moz-columns: 3; columns: 3; } h5 { column-span: all; } <style> <div class="trois-colonnes"> <p>Long texte sur 3 colonnes.</p> <h5>En principe sur une seule colonnes.</h5> <p>Long texte sur 3 colonnes.</p> </div>
Boîte flexible avec le module Flex
Enfin il ne faut pas négliger le module « flex » qui permet aussi de régler la plupart des problèmes historiques de positionnement, d’alignement et de remplissage. Les structures HTML ou même les systèmes de grille (grid) ne s’en passeront plus! Mais attention, certaines implémentations réagissent fort mal selon la plate-forme.
Conclusion
Il va sans dire que ce n’est pas si bleu et blanc, tout est dans la nuance. Il est loin le jour ou la table HTML sera remisée. Si elle a toujours le défaut de s’afficher en bloc, la plupart de ses avantages sont maintenant possibles en CSS. Et si le CSS ne permet pas encore le colspan
la propriété table-layout: fixed;
permet d’optimiser l’affichage d’une table HTML.
En conclusion, le CSS semble indiqué pour créer des structures HTML flexibles et adaptatives. Notamment pas l’entremise de structure flex
et des balises HTML5 header, nav, aside, main, section, footer! Je ne suis pas encore rendu à l’utiliser pour afficher des données sous forme tabloïde. La table HTML reste toujours une des meilleurs solutions pour ce faire.