Scan gratuit

4 novembre 2026

Tableau accessible HTML : th, scope, headers et caption expliqués avec du code

Un tableau accessible HTML repose sur un principe simple : chaque cellule d'en-tête est balisée avec <th>, chaque cellule de données avec <td>, et la relation entre les deux est définie par le balisage ; pour les tableaux plus complexes, des associations explicites peuvent être nécessaires. C'est ce que rappelle le tutoriel tableaux du W3C (WAI) : les technologies d'assistance s'appuient sur ce balisage pour donner du contexte à l'utilisateur. Selon la complexité du tableau, vous utiliserez en plus l'attribut scope, ou les attributs id et headers, et, dans la plupart des cas, un élément <caption> pour donner un titre au tableau. Ce guide reprend chaque cas avec des exemples de code prêts à adapter : tableau à un seul en-tête, tableau à en-têtes de lignes et de colonnes, en-têtes fusionnés, tableau complexe à plusieurs niveaux, légende et résumé, puis les erreurs à ne pas commettre.

Pourquoi le balisage d'un tableau accessible HTML est indispensable

Un tableau sans balisage structurel, qui ne distingue pas les cellules d'en-tête des cellules de données et ne les relie pas correctement, crée des obstacles. Se fier uniquement aux indices visuels ne suffit pas : il faut que les en-têtes et les données puissent être déterminés par programme.

Concrètement, un lecteur d'écran lit une cellule à la fois et annonce les en-têtes de ligne et de colonne qui lui sont associés : l'utilisateur ne perd pas le contexte en se déplaçant dans le tableau. D'autres personnes affichent les données autrement, par exemple avec des feuilles de style personnalisées qui font ressortir les en-têtes, changent la taille du texte et les couleurs, ou présentent l'information sous forme de liste plutôt que de grille. Ces restitutions alternatives ne fonctionnent que si le code du tableau est correctement structuré.

Côté WCAG, le tutoriel du W3C rattache ces pratiques au critère de succès 1.3.1 Information et relations (niveau A) et aux techniques H51 (utiliser le balisage de tableau pour présenter une information tabulaire), H63 (utiliser l'attribut scope pour associer les cellules d'en-tête aux cellules de données dans les tableaux de données) et H39 (utiliser l'élément caption pour associer une légende à un tableau de données).

Tableau simple : <th> pour les en-têtes et scope pour lever l'ambiguïté

Le cas le plus simple est un tableau avec un seul en-tête, soit sur la première ligne, soit dans la première colonne, et des données qui se distinguent clairement d'une colonne à l'autre. Pour un petit tableau de concerts (date, événement, lieu), baliser la première ligne avec <th> et le reste avec <td> n'est acceptable que parce que le tableau est petit et que les données de chaque colonne sont nettement différentes, ce qui rend la relation entre en-têtes et données évidente. Le W3C signale toutefois que certains lecteurs d'écran liront « Date – Event – Venue » dans la cellule « Venue », car la direction des <th> est ambiguë.

Dès que les données ne se distinguent plus d'elles-mêmes, ajoutez l'attribut scope. Dans l'exemple du W3C, une liste de collectionneurs avec nom, prénom et ville : sans savoir à quel en-tête correspond chaque cellule, impossible de distinguer un nom d'un prénom ou d'une ville. La valeur col de scope définit la direction des en-têtes et les associe aux cellules de données de leur colonne. Le W3C précise que scope est aussi nécessaire pour les tableaux plus grands qui n'ont qu'une ligne ou une colonne d'en-têtes.

<table>
  <caption>Collectionneurs d'ours en peluche</caption>
  <tr>
    <th scope="col">Nom</th>
    <th scope="col">Prénom</th>
    <th scope="col">Ville</th>
  </tr>
  <tr>
    <td>Phoenix</td>
    <td>Imari</td>
    <td>Henry</td>
  </tr>
  […]
</table>

En-têtes de lignes et de colonnes : scope="col" et scope="row"

Lorsqu'un tableau a à la fois un en-tête de colonnes et un en-tête de lignes, la relation entre en-têtes et données devient vite ambiguë. Utilisez <th> pour toutes les cellules d'en-tête et déclarez la direction de chacune : scope="col" indique que l'en-tête s'applique à toute la colonne, scope="row" à toute la ligne.

L'exemple du W3C est un tableau de créneaux de livraison : les jours de la semaine en haut, les plages horaires à gauche, et dans les cellules « Ouvert » ou « Fermé ». Ces mentions n'ont de sens que si l'on peut les rattacher à un jour et à une heure précis. La cellule en haut à gauche, vide, reste un <td>.

La même technique fonctionne quand les en-têtes de lignes ne sont pas dans la première colonne. Dans un tableau de congés où la première colonne contient un identifiant et la deuxième le nom de la personne, le nom est balisé <th scope="row"> : il s'applique alors aux cellules situées à sa gauche comme à sa droite.

<table>
  <caption>Créneaux de livraison</caption>
  <tr>
    <td></td>
    <th scope="col">Lundi</th>
    <th scope="col">Mardi</th>
  </tr>
  <tr>
    <th scope="row">09:00 – 11:00</th>
    <td>Fermé</td>
    <td>Ouvert</td>
  </tr>
  […]
</table>

En-têtes fusionnés : colgroup, rowgroup, thead et tbody

Quand une cellule d'en-tête s'étend sur plusieurs colonnes (colspan) ou plusieurs lignes (rowspan), elle doit être associée aux cellules correspondantes du groupe. On utilise pour cela scope="colgroup" ou scope="rowgroup". Mais avant, la structure des groupes doit être définie dans le balisage.

Pour les colonnes, chaque colonne est identifiée par un élément <col> en partant de la gauche ; si un en-tête couvre plusieurs colonnes, un <colgroup> avec un attribut span remplace ce nombre d'éléments <col>. Le total des <col> (hors <colgroup>) et des colonnes indiquées par les span des <colgroup> doit être égal au nombre total de colonnes du tableau. Pour les lignes, un groupe est défini par <thead>, <tbody> ou <tfoot>.

<table>
  <col>
  <colgroup span="2"></colgroup>
  <colgroup span="2"></colgroup>
  <tr>
    <td rowspan="2"></td>
    <th colspan="2" scope="colgroup">Mars</th>
    <th colspan="2" scope="colgroup">Vénus</th>
  </tr>
  <tr>
    <th scope="col">Fabriqués</th>
    <th scope="col">Vendus</th>
    <th scope="col">Fabriqués</th>
    <th scope="col">Vendus</th>
  </tr>
  <tr>
    <th scope="row">Ours en peluche</th>
    <td>50 000</td>
    <td>30 000</td>
    <td>100 000</td>
    <td>80 000</td>
  </tr>
  […]
</table>

Tableau complexe : associer chaque cellule avec headers et id

Certains tableaux sont trop complexes pour qu'on puisse associer en-têtes et données de façon strictement horizontale ou verticale. Le W3C cite deux cas : les tableaux dont les en-têtes de colonnes se répètent ou changent en cours de tableau, et ceux où trois en-têtes ou plus sont associés à chaque cellule de données.

La méthode : chaque <th> reçoit un id unique dans tout le document, et chaque <td> liste dans son attribut headers le ou les id des en-têtes qui le concernent, séparés par des espaces. Dans l'exemple du W3C sur la disponibilité de logements de vacances, la cellule « 11 » est reliée à la fois à la ville (Paris), au nombre de chambres (1 chambre) et au type de logement (studio).

Astuce tirée du tutoriel : dans un tableau de contacts fournisseurs où les en-têtes changent à mi-tableau, les cellules d'en-tête elles-mêmes pointent vers une cellule vide portant l'id « blank », ce qui empêche certaines technologies d'assistance de lire un en-tête pour ces cellules d'en-tête.

Avant de vous lancer, demandez-vous si le tableau doit vraiment rester aussi complexe. Le W3C suggère, dans bien des cas, de le scinder en tableaux plus petits : l'information devient plus facile à comprendre pour tout le monde, plus facile à coder, et les tableaux simples sont bien mieux pris en charge par les outils de création de contenu, y compris les éditeurs WYSIWYG.

[…]
<tr>
  <th id="par" colspan="5" scope="colgroup">Paris</th>
</tr>
<tr>
  <th id="pbed1">1 chambre</th>
  <td headers="par pbed1 stud">11</td>
  <td headers="par pbed1 apt">20</td>
  […]
</tr>

Légende avec <caption> et résumé des tableaux complexes

La légende fonctionne comme un titre pour le tableau. La plupart des lecteurs d'écran annoncent son contenu ; elle aide l'utilisateur à trouver le tableau, à comprendre son sujet et à décider s'il veut le lire. Pour les personnes qui naviguent en « mode tableaux », de tableau en tableau, la légende est le principal moyen de les identifier. Elle se code avec l'élément <caption>, placé directement comme enfant de <table>, et doit rester un titre court, par exemple « Concerts ».

Le résumé, lui, décrit l'organisation des données et aide à naviguer ; il n'est généralement utile que pour les tableaux complexes. Si vous fournissez les deux, le résumé ne doit pas répéter une information déjà présente dans la légende. Le W3C rappelle que légende et résumé ne sont pas exigés dans tous les cas pour respecter les WCAG, mais qu'ils sont des moyens assez simples de fournir une information souvent nécessaire.

<table>
  <caption>Disponibilité des logements de vacances<br>
    <span>La première colonne indique la ville et la taille du logement, les autres colonnes le type et le nombre de logements disponibles</span>
  </caption>
  […]
</table>

Ce qu'il ne faut pas faire dans un tableau HTML

La page « Tips and Tricks » du tutoriel regroupe plusieurs pratiques à éviter.

Questions fréquentes

Comment rendre un tableau HTML accessible ?

Balisez les cellules d'en-tête avec <th> et les cellules de données avec <td>. Ajoutez scope="col" ou scope="row" quand la direction des en-têtes est ambiguë, scope="colgroup" ou scope="rowgroup" pour les en-têtes fusionnés, id et headers quand l'association ne peut pas être strictement horizontale ou verticale (en-têtes qui changent en cours de tableau, trois en-têtes ou plus par cellule). Dans la plupart des cas, donnez aussi un titre au tableau avec <caption> : ce n'est pas exigé dans tous les cas par les WCAG, mais c'est utile.

Quelle est la différence entre scope et headers ?

scope indique la direction d'un en-tête : col, row, colgroup ou rowgroup. Il suffit tant que l'association est strictement horizontale ou verticale. headers, placé en général sur une cellule de données, liste explicitement les id des en-têtes associés ; il sert quand les en-têtes changent en cours de tableau ou quand trois en-têtes ou plus concernent chaque cellule.

La balise caption est-elle obligatoire dans un tableau ?

Selon le W3C, légende et résumé ne sont pas exigés dans tous les cas pour respecter les WCAG. La légende est cependant utile dans la plupart des situations : la plupart des lecteurs d'écran l'annoncent et elle est le principal moyen d'identifier un tableau en mode tableaux.

Faut-il mettre scope sur un tableau simple ?

Pas toujours : des <th> sans scope ne sont acceptables que pour un petit tableau dont les données se distinguent clairement d'une colonne à l'autre ; même dans ce cas, certains lecteurs d'écran liront « Date – Event – Venue » dans la cellule « Venue », car la direction des <th> est ambiguë. Dès que les données sont ambiguës, ou pour un tableau plus grand avec une seule ligne ou colonne d'en-têtes, ajoutez scope.

Peut-on utiliser un tableau HTML pour la mise en page ?

Non, le W3C recommande CSS pour la mise en page. Pour un tableau de mise en page déjà en place, n'utilisez ni les éléments structurels comme <th> ou <caption>, ni les attributs vus dans ce guide (scope, headers…), et ajoutez role="presentation" sur l'élément <table>.

À lire aussi sur Conformly

Sources

Article appuyé sur les sources officielles citées en fin de page.