Un tableau HTML se construit en quelques balises, mais sans CSS il ressemble à un relevé bancaire des années 1990. Ce guide reprend les bases de la structure, les cinq propriétés CSS qui changent tout, puis 8 modèles de tableaux CSS prêts à copier : épuré, zébré, en carte, avec pastilles de statut, comparatif de tarifs, mode sombre, grand tableau défilant et version mobile.
Tous les codes de cet article ont été testés tels quels : chaque capture est le rendu du code affiché, dans Chrome. Nous avons aussi appliqué un modèle au bloc Tableau de WordPress (version 7.1.4) : copier le CSS ne suffit pas, nous expliquons pourquoi et comment l’adapter.
La structure d’un tableau HTML
Voici un tableau complet et correct. C’est la base de tous les modèles de l’article :
<table class="tab-epure">
<caption>Dernières commandes</caption>
<thead>
<tr><th scope="col">Commande</th><th scope="col">Client</th><th scope="col">Date</th><th scope="col">Statut</th><th scope="col" class="num">Montant</th></tr>
</thead>
<tbody>
<tr><td>#1042</td><td>Claire Martin</td><td>03/11/2026</td><td>Terminée</td><td class="num">89,90 €</td></tr>
<tr><td>#1041</td><td>Hugo Bernard</td><td>02/11/2026</td><td>En cours</td><td class="num">24,50 €</td></tr>
<tr><td>#1040</td><td>Léa Petit</td><td>02/11/2026</td><td>Terminée</td><td class="num">132,00 €</td></tr>
<tr><td>#1039</td><td>Nicolas Roux</td><td>31/10/2026</td><td>En attente</td><td class="num">56,40 €</td></tr>
<tr><td>#1038</td><td>Inès Moreau</td><td>30/10/2026</td><td>Annulée</td><td class="num">109,50 €</td></tr>
</tbody>
<tfoot>
<tr><th scope="row" colspan="4">Total</th><td class="num">412,30 €</td></tr>
</tfoot>
</table>Les balises à connaître :
<table>contient tout le tableau ;<caption>donne son titre au tableau, lu en premier par les lecteurs d’écran ;<thead>,<tbody>et<tfoot>séparent l’en-tête, le corps et le pied (ici, le total) ;<tr>crée une ligne,<th>une cellule d’en-tête et<td>une cellule de données ;scope="col"ouscope="row"indique si l’en-tête vaut pour une colonne ou pour une ligne. C’est invisible, mais c’est ce qui permet à un lecteur d’écran d’annoncer « Montant : 89,90 € ».
Sans aucun CSS, le navigateur affiche ceci :

Fusionner des cellules : colspan et rowspan
colspan étend une cellule sur plusieurs colonnes, rowspan sur plusieurs lignes. C’est ce que fait la ligne du total : la cellule « Total » occupe les quatre premières colonnes.
<tr><th scope="row" colspan="4">Total</th><td class="num">412,30 €</td></tr>Vérifiez toujours le compte : une ligne doit totaliser le même nombre de colonnes que les autres (ici 4 + 1 = 5), sinon le tableau se décale.
Les 5 propriétés CSS qui changent tout
border-collapse: collapsefusionne les bordures des cellules voisines. Sans lui, chaque cellule a sa propre bordure et on obtient des doubles traits.paddingsurthettddonne de l’air. C’est la retouche la plus visible :.7em 1emest un bon point de départ.text-align: à gauche pour le texte, à droite pour les nombres, pour que les virgules s’alignent. Ajoutezfont-variant-numeric: tabular-nums, qui donne la même largeur à tous les chiffres.:nth-child(even)colore une ligne sur deux, sans toucher au HTML.width: 100%fait occuper au tableau toute la largeur disponible. Pour des colonnes de largeur égale, ajouteztable-layout: fixed(au risque de couper les mots longs, nous le verrons avec WordPress).
8 modèles de tableaux CSS prêts à copier
Les modèles 1 à 4 et 6 utilisent le HTML ci-dessus : remplacez simplement la classe tab-epure par celle du modèle (tab-zebre, tab-carte…). Chaque modèle préfixe toutes ses règles par sa classe : il ne touche à aucun autre tableau de votre site.
1. Le tableau épuré
Le plus sobre : pas de fond, de fines lignes de séparation, un en-tête en petites capitales. Il convient à presque tous les sites.

.tab-epure {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-epure caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-epure th,
.tab-epure td {
padding: .75em 1em;
text-align: left;
border-bottom: 1px solid #e3e8ee;
}
.tab-epure thead th {
font-size: .8em;
text-transform: uppercase;
letter-spacing: .05em;
color: #6b7785;
border-bottom: 2px solid #263445;
}
.tab-epure .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.tab-epure tfoot th,
.tab-epure tfoot td {
font-weight: 700;
border-bottom: 0;
}2. Le tableau zébré avec survol
Une ligne sur deux est teintée et la ligne survolée par la souris s’éclaire (sur la capture, la troisième ligne). Idéal pour les tableaux longs, où l’œil perd facilement sa ligne.

.tab-zebre {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-zebre caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-zebre th,
.tab-zebre td {
padding: .7em 1em;
text-align: left;
}
.tab-zebre thead th {
background: #263445;
color: #fff;
}
.tab-zebre tbody tr:nth-child(even) {
background: #f4f7fa;
}
.tab-zebre tbody tr:hover {
background: #dff5ef;
}
.tab-zebre .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.tab-zebre tfoot th,
.tab-zebre tfoot td {
font-weight: 700;
border-top: 2px solid #263445;
}3. Le tableau « carte » : coins arrondis et ombre
Le tableau devient un bloc posé sur la page. Attention : les coins arrondis ne fonctionnent pas avec border-collapse: collapse, d’où le separate et le border-spacing: 0.

.tab-carte {
width: 100%;
border-collapse: separate; /* indispensable pour arrondir les coins */
border-spacing: 0;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(38, 52, 69, .12);
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
background: #fff;
}
.tab-carte caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-carte th,
.tab-carte td {
padding: .8em 1.1em;
text-align: left;
border-bottom: 1px solid #eef1f4;
}
.tab-carte thead th {
background: #f9735b;
color: #fff;
border-bottom: 0;
}
.tab-carte .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.tab-carte tfoot th,
.tab-carte tfoot td {
font-weight: 700;
background: #fff4f1;
border-bottom: 0;
}4. Le tableau de suivi avec pastilles de statut
Pour un suivi de commandes, de tâches ou de tickets. Le statut passe dans une pastille colorée : il faut entourer le texte d’un <span> dans le HTML.
<td><span class="statut statut--ok">Terminée</span></td>
<td><span class="statut statut--cours">En cours</span></td>
<td><span class="statut statut--attente">En attente</span></td>
<td><span class="statut statut--annule">Annulée</span></td>
.tab-statuts {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-statuts caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-statuts th,
.tab-statuts td {
padding: .7em 1em;
text-align: left;
border-bottom: 1px solid #e3e8ee;
}
.tab-statuts thead th {
font-size: .85em;
color: #6b7785;
}
.tab-statuts .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.tab-statuts tfoot th,
.tab-statuts tfoot td {
font-weight: 700;
border-bottom: 0;
}
.statut {
display: inline-block;
padding: .15em .75em;
border-radius: 999px;
font-size: .85em;
font-weight: 600;
}
.statut--ok { background: #dff5ef; color: #1d6b55; }
.statut--cours { background: #e3edfb; color: #2457a6; }
.statut--attente { background: #fff3d6; color: #8a5a00; }
.statut--annule { background: #fde4e1; color: #a3302a; }La couleur ne doit jamais être la seule information : le mot reste écrit dans la pastille, pour les daltoniens comme pour les lecteurs d’écran.
5. Le tableau comparatif de tarifs
Trois formules côte à côte, celle à mettre en avant en couleur. Les coches sont doublées d’un texte masqué (« Inclus », « Non inclus ») : un lecteur d’écran ne sait pas lire un « ✓ ».

<table class="tab-tarifs">
<caption>Comparer les formules</caption>
<thead>
<tr>
<td></td>
<th scope="col">Découverte <span class="prix">0 €</span></th>
<th scope="col" class="vedette">Essentiel <span class="prix">9 €</span></th>
<th scope="col">Pro <span class="prix">19 €</span></th>
</tr>
</thead>
<tbody>
<tr><th scope="row">Produits en ligne</th><td>20</td><td class="vedette">500</td><td>Illimité</td></tr>
<tr><th scope="row">Paiement par carte</th><td class="oui">✓<span class="masque">Inclus</span></td><td class="vedette oui">✓<span class="masque">Inclus</span></td><td class="oui">✓<span class="masque">Inclus</span></td></tr>
<tr><th scope="row">Codes promo</th><td class="non">–<span class="masque">Non inclus</span></td><td class="vedette oui">✓<span class="masque">Inclus</span></td><td class="oui">✓<span class="masque">Inclus</span></td></tr>
<tr><th scope="row">Statistiques détaillées</th><td class="non">–<span class="masque">Non inclus</span></td><td class="vedette non">–<span class="masque">Non inclus</span></td><td class="oui">✓<span class="masque">Inclus</span></td></tr>
<tr><th scope="row">Assistance</th><td>E-mail</td><td class="vedette">E-mail et chat</td><td>Prioritaire</td></tr>
</tbody>
</table>.tab-tarifs {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
text-align: center;
}
.tab-tarifs caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-tarifs th,
.tab-tarifs td {
padding: .8em 1em;
border-bottom: 1px solid #e3e8ee;
}
.tab-tarifs tbody th {
text-align: left;
font-weight: 400;
}
.tab-tarifs thead th {
font-size: 1.05em;
border-bottom: 2px solid #263445;
}
.tab-tarifs .prix {
display: block;
font-size: 1.5em;
font-weight: 800;
}
.tab-tarifs .vedette {
background: #fff4f1;
}
.tab-tarifs thead .vedette {
background: #f9735b;
color: #fff;
border-radius: 10px 10px 0 0;
}
.tab-tarifs .oui { color: #1d6b55; font-weight: 700; }
.tab-tarifs .non { color: #b0b8c1; }
.masque {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
}6. Le tableau en mode sombre
Pour un site ou une section au fond sombre. Évitez le noir pur et le blanc pur : un bleu nuit et un gris clair fatiguent moins les yeux.

.tab-sombre {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #e6ebf0;
background: #1e2733;
}
.tab-sombre caption {
text-align: left;
font-weight: 700;
padding: .8em 1em;
background: #1e2733;
}
.tab-sombre th,
.tab-sombre td {
padding: .75em 1em;
text-align: left;
border-bottom: 1px solid #36414f;
}
.tab-sombre thead th {
background: #2b3645;
color: #9fb0c3;
font-size: .85em;
text-transform: uppercase;
letter-spacing: .05em;
}
.tab-sombre tbody tr:hover {
background: #263241;
}
.tab-sombre .num {
text-align: right;
font-variant-numeric: tabular-nums;
}
.tab-sombre tfoot th,
.tab-sombre tfoot td {
font-weight: 700;
color: #7fe0c4;
border-bottom: 0;
}Pour qu’il ne s’active que chez les visiteurs qui ont choisi le mode sombre, placez ces règles dans @media (prefers-color-scheme: dark) { … }.
7. Le grand tableau avec en-tête et première colonne figés
Pour un tableau trop haut ou trop large : il défile dans son cadre, l’en-tête reste visible en haut et le numéro de commande à gauche. Sur la capture, le tableau a défilé vers le bas et vers la droite : la colonne « Client » passe sous la première colonne.

<div class="tab-defile" tabindex="0" role="region" aria-label="Commandes (tableau défilant)">
<table>
<thead>
<tr><th scope="col">Commande</th><th scope="col">Client</th><th scope="col">Date</th><th scope="col">Ville</th><th scope="col">Paiement</th><th scope="col">Livraison</th><th scope="col">Statut</th><th scope="col">Montant</th></tr>
</thead>
<tbody>
<tr><th scope="row">#1042</th><td>Claire Martin</td><td>03/11/2026</td><td>Lyon</td><td>Carte</td><td>Colissimo</td><td>Terminée</td><td>89,90 €</td></tr>
<tr><th scope="row">#1041</th><td>Hugo Bernard</td><td>02/11/2026</td><td>Nantes</td><td>PayPal</td><td>Point relais</td><td>En cours</td><td>24,50 €</td></tr>
<tr><th scope="row">#1040</th><td>Léa Petit</td><td>02/11/2026</td><td>Lille</td><td>Carte</td><td>Colissimo</td><td>Terminée</td><td>132,00 €</td></tr>
<tr><th scope="row">#1039</th><td>Nicolas Roux</td><td>31/10/2026</td><td>Rennes</td><td>Virement</td><td>Retrait</td><td>En attente</td><td>56,40 €</td></tr>
<tr><th scope="row">#1038</th><td>Inès Moreau</td><td>30/10/2026</td><td>Metz</td><td>Carte</td><td>Point relais</td><td>Annulée</td><td>109,50 €</td></tr>
<tr><th scope="row">#1037</th><td>Paul Girard</td><td>29/10/2026</td><td>Nice</td><td>Carte</td><td>Colissimo</td><td>Terminée</td><td>45,00 €</td></tr>
<tr><th scope="row">#1036</th><td>Emma Lefèvre</td><td>29/10/2026</td><td>Dijon</td><td>PayPal</td><td>Colissimo</td><td>En cours</td><td>18,90 €</td></tr>
<tr><th scope="row">#1035</th><td>Lucas Fontaine</td><td>28/10/2026</td><td>Tours</td><td>Carte</td><td>Point relais</td><td>Terminée</td><td>76,20 €</td></tr>
<tr><th scope="row">#1034</th><td>Chloé Garnier</td><td>27/10/2026</td><td>Brest</td><td>Virement</td><td>Colissimo</td><td>Terminée</td><td>210,00 €</td></tr>
<tr><th scope="row">#1033</th><td>Tom Chevalier</td><td>26/10/2026</td><td>Annecy</td><td>Carte</td><td>Retrait</td><td>En attente</td><td>39,90 €</td></tr>
</tbody>
</table>
</div>.tab-defile {
max-height: 280px;
overflow: auto;
border: 1px solid #e3e8ee;
border-radius: 8px;
}
.tab-defile table {
border-collapse: separate; /* sticky fonctionne mieux qu'avec collapse */
border-spacing: 0;
min-width: 900px;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-defile th,
.tab-defile td {
padding: .65em 1em;
text-align: left;
white-space: nowrap;
border-bottom: 1px solid #e3e8ee;
background: #fff;
}
.tab-defile thead th {
position: sticky;
top: 0;
z-index: 2;
background: #263445;
color: #fff;
}
.tab-defile tbody th {
position: sticky;
left: 0;
z-index: 1;
font-weight: 600;
border-right: 1px solid #e3e8ee;
}
.tab-defile thead th:first-child {
left: 0;
z-index: 3;
}Le cadre reçoit tabindex="0" pour qu’on puisse le faire défiler au clavier, et role="region" avec un aria-label pour qu’un lecteur d’écran l’annonce.
8. Le tableau responsive qui s’empile sur mobile
Sous 600 pixels de large, chaque ligne devient une carte où chaque valeur est précédée de son intitulé. Il faut répéter l’intitulé de la colonne dans un attribut data-label sur chaque cellule :
<tr><td data-label="Commande">#1042</td><td data-label="Client">Claire Martin</td><td data-label="Date">03/11/2026</td><td data-label="Statut">Terminée</td><td class="num" data-label="Montant">89,90 €</td></tr>
.tab-mobile {
width: 100%;
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-mobile caption {
text-align: left;
font-weight: 700;
padding-bottom: .6em;
}
.tab-mobile th,
.tab-mobile td {
padding: .7em 1em;
text-align: left;
border-bottom: 1px solid #e3e8ee;
}
.tab-mobile .num {
text-align: right;
}
@media (max-width: 600px) {
.tab-mobile,
.tab-mobile caption,
.tab-mobile tbody,
.tab-mobile tfoot {
display: block;
}
.tab-mobile thead {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
}
.tab-mobile tr {
display: block;
margin-bottom: 1em;
border: 1px solid #e3e8ee;
border-radius: 10px;
padding: .3em .2em;
}
.tab-mobile td,
.tab-mobile tfoot th {
display: flex;
justify-content: space-between;
gap: 1em;
border-bottom: 0;
padding: .45em .8em;
}
.tab-mobile td::before {
content: attr(data-label);
font-weight: 600;
color: #6b7785;
}
.tab-mobile tfoot td::before {
content: none;
}
.tab-mobile tfoot tr {
display: flex;
justify-content: space-between;
font-weight: 700;
background: #f4f7fa;
}
}Sur ordinateur, ce tableau s’affiche comme le modèle épuré.
Rendre un tableau responsive : laquelle des deux méthodes ?
- Le défilement horizontal (le cadre du modèle 7) : on entoure le tableau d’un
<div>avecoverflow-x: auto. C’est la méthode la plus simple et la plus sûre, et elle convient aux tableaux qu’on compare colonne par colonne (tarifs, caractéristiques). - L’empilement (modèle 8) : plus confortable à lire sur téléphone pour des listes (commandes, contacts). Contrepartie : en changeant le
displaydes lignes et des cellules, certains lecteurs d’écran ne reconnaissent plus le tableau comme tel. Si l’accessibilité est un enjeu fort, préférez le défilement.
Dans WordPress : appliquer un modèle au bloc Tableau (testé)
Nous avons créé ce même tableau avec le bloc Tableau de WordPress 7.1.4 (thème Twenty Twenty-Five), puis appliqué le modèle zébré. Voici ce que nous avons constaté.
Piège 1 : la largeur fixe des cellules coupe les mots. Un nouveau bloc Tableau a l’option « Cellules de tableau à largeur fixe » activée par défaut. Toutes les colonnes ont alors la même largeur, et les mots qui ne tiennent pas sont coupés en plein milieu : « Comman » puis « de » à la ligne, « 03/11/202 » puis « 6 ».

Désactivez-la dans les réglages du bloc (colonne de droite, onglet Bloc). Les colonnes s’adaptent alors à leur contenu.
Étape 1 : donner une classe au bloc. Toujours dans les réglages du bloc, ouvrez Avancé et tapez tab-zebre dans Classe(s) CSS additionnelle(s).

Étape 2 : ajouter le CSS au site. Avec un thème à blocs (Twenty Twenty-Five, par exemple) : Apparence > Éditeur > Styles, puis le menu ⋮ et CSS additionnel. Avec un thème classique (Astra, Blocksy, OceanWP…) : Apparence > Personnaliser > CSS additionnel.

Piège 2 : le CSS du modèle ne s’applique qu’à moitié. Collé tel quel, le modèle zébré colore bien l’en-tête et les lignes, mais trois choses résistent :
- les bordures noires du bloc restent autour de chaque cellule, car WordPress ajoute les siennes ;
- la légende ne bouge pas : le bloc ne génère pas de
<caption>mais un<figcaption>, placé sous le tableau ; - la classe n’est pas posée sur le
<table>mais sur le<figure>qui l’entoure : la règle.tab-zebre { width: 100%; … }vise donc le mauvais élément.
Le bloc ne permet pas non plus d’ajouter une classe num à une cellule : on aligne la dernière colonne avec :last-child. Voici la version adaptée au bloc, celle que nous avons validée :
/* Bloc Tableau : classe « tab-zebre » dans Avancé > Classe(s) CSS additionnelle(s) */
.tab-zebre {
display: flex;
flex-direction: column;
}
.tab-zebre figcaption {
order: -1; /* la légende passe au-dessus du tableau */
text-align: left;
font-weight: 700;
margin: 0 0 .6em;
}
.tab-zebre table {
border-collapse: collapse;
font: 15px/1.5 system-ui, sans-serif;
color: #263445;
}
.tab-zebre thead,
.tab-zebre tfoot,
.tab-zebre th,
.tab-zebre td {
border: 0; /* retire les bordures ajoutées par le bloc */
}
.tab-zebre th,
.tab-zebre td {
padding: .7em 1em;
text-align: left;
}
.tab-zebre thead th {
background: #263445;
color: #fff;
}
.tab-zebre tbody tr:nth-child(even) {
background: #f4f7fa;
}
.tab-zebre tbody tr:hover {
background: #dff5ef;
}
.tab-zebre th:last-child,
.tab-zebre td:last-child {
text-align: right; /* colonne des montants */
font-variant-numeric: tabular-nums;
}
.tab-zebre tfoot td {
font-weight: 700;
border-top: 2px solid #263445;
}Le résultat sur le site, avec la légende remontée au-dessus du tableau :

La même adaptation vaut pour les autres modèles : remplacez .tab-xxx { … } par .tab-xxx table { … }, remettez les bordures à zéro et visez figcaption au lieu de caption.
À noter : WordPress 7 propose aussi un champ CSS additionnel dans les réglages avancés de chaque bloc. Il ne vaut que pour ce bloc : pratique pour une retouche ponctuelle, mais une classe et un CSS commun restent la bonne méthode dès que vous avez plusieurs tableaux.
Accessibilité : 4 réflexes
- Un titre dans
<caption>(ou la légende du bloc WordPress). - Des
<th>avecscopepour les en-têtes, jamais des<td>en gras. - Un contraste suffisant entre le texte et le fond, y compris pour les lignes zébrées et les pastilles.
- Pas de tableau pour la mise en page : un tableau sert à des données. Pour placer des blocs côte à côte, il y a Flexbox, Grid ou le bloc Colonnes de WordPress.
Questions fréquentes
Comment centrer un tableau en CSS ? Donnez-lui une largeur inférieure à 100 % et margin: 0 auto, par exemple width: 80%; margin: 0 auto;.
Comment mettre une bordure autour de chaque cellule ? border: 1px solid #ccc sur th et td, avec border-collapse: collapse sur le tableau pour éviter les doubles traits.
Comment fixer la largeur d’une colonne ? Donnez une largeur à la cellule d’en-tête (th:first-child { width: 120px; }) ou utilisez <colgroup> et <col style="width: 120px">. Avec table-layout: fixed, le navigateur respecte strictement ces largeurs.
Faut-il une extension pour faire des tableaux dans WordPress ? Pour un tableau simple, non : le bloc Tableau et un peu de CSS suffisent. Une extension (TablePress, par exemple) devient utile pour trier, filtrer ou paginer de gros tableaux, ou les importer depuis un tableur.






