Composant · Données et contenus riches

Tableau de données accessible : caption, th et scope

Baliser un tableau de données accessible : caption associé, en-têtes th avec scope, critères RGAA de la thématique 5 et défilement maîtrisé à 320 px.

Un tableau de données présente des informations en lignes et colonnes, sans interactivité : liste de prix, rapport, comparatif. L'élément à préférer est <table> avec <caption>, <thead> et des <th> munis de scope : c'est toute la thématique 5 du RGAA, entièrement une affaire de balisage. Aucun script, aucun modèle clavier : un tableau standard bien balisé est accessible par construction.

Cette fiche couvre le tableau standard, celui que scope suffit à décrire. Dès que des en-têtes fusionnent ou se superposent sur plusieurs niveaux, les techniques changent : le guide Tableaux complexes accessibles détaille pas à pas la simplification, les cellules fusionnées et les associations headers/id.

Quand ce motif est le mauvais choix

  • Pour de la mise en page, ne pas utiliser de tableau : CSS grid et flexbox existent. Un tableau de mise en forme résiduel doit rester compréhensible une fois linéarisé et porter role="presentation" (critère 5.3), sans aucun élément propre aux tableaux de données (critère 5.8).
  • Pour un tableau que l'utilisateur manipule cellule par cellule (édition, sélection, tableur), c'est le motif grille (role="grid"), qui ajoute un modèle clavier complet. Un tableau en lecture seule ne doit jamais recevoir role="grid".
  • Pour une hiérarchie de lignes dépliables avec cellules interactives, voir la fiche grille arborescente ; si les lignes se déplient mais restent en lecture seule, un simple <table> avec des boutons aria-expanded suffit.
  • Des <div> stylés en tableau ne sont pas un tableau : sans lignes, colonnes ni en-têtes, un lecteur d'écran lit un seul bloc de texte plat.

Critères RGAA applicables

Interaction clavier attendue

Aucune interaction propre : un tableau de données se lit avec les touches habituelles de navigation, et les raccourcis de navigation de tableau du lecteur d'écran.

ToucheAction
TabNe s'arrête pas sur le tableau lui-même. Une seule exception : le conteneur défilant d'un tableau large, qui doit être focusable.
FlèchesDans un conteneur défilant focalisé : font défiler les colonnes hors écran.

L'exception est importante : un conteneur overflow-x: auto défile à la molette ou au doigt, mais sans tabindex="0" l'utilisateur au clavier n'a aucun moyen d'atteindre les colonnes de droite.

Rôles et attributs ARIA

Aucun ARIA n'est nécessaire sur un <table> bien balisé : les rôles table, row, cell, columnheader et rowheader sont implicites. Structure de référence :

<table>
  <!-- PREMIER enfant de <table> : c'est le nom du tableau (critère 5.4),
       non interchangeable avec un titre posé au-dessus. -->
  <caption>Chiffre d'affaires par région, T3 2026</caption>
  <thead>
    <tr>
      <th scope="col">Région</th>
      <th scope="col">Chiffre d'affaires</th>
      <th scope="col">Croissance</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <!-- scope="row" : l'oubli le plus courant. Sans lui, « 2,4 M€ »
           est annoncé sans jamais rattacher la région. -->
      <th scope="row">Europe</th>
      <td>2,4 M€</td>
      <td>+12 %</td>
    </tr>
    <tr>
      <th scope="row">Asie-Pacifique</th>
      <td>1,8 M€</td>
      <td>+31 %</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row">Total</th>
      <td>4,2 M€</td>
      <td>+19 %</td>
    </tr>
  </tfoot>
</table>

Avec scope en place, le lecteur d'écran annonce « Europe, Chiffre d'affaires, 2,4 M€ » en traversant la ligne : les en-têtes voyagent avec la cellule. C'est tout l'objet de la thématique 5. Pour un tableau complexe (en-têtes fusionnés sur plusieurs niveaux), scope ne sait plus exprimer les relations : il faut donner un id à chaque <th> et lister ces id dans l'attribut headers de chaque cellule, technique détaillée dans le guide Tableaux complexes accessibles.

Le tableau large se gère par un conteneur défilant, jamais en laissant la page entière défiler :

<!-- Les tableaux sont la première cause de défilement horizontal à
     320 px. Le conteneur rend le tableau défilant ; tabindex="0" le
     rend défilable AU CLAVIER ; le rôle et le nom disent ce qui défile
     (critère 10.11). -->
<div role="region" aria-labelledby="ca-caption" tabindex="0"
     class="defilement-tableau">
  <table>
    <caption id="ca-caption">Chiffre d'affaires par région, T3 2026</caption>
    ...
  </table>
</div>
.defilement-tableau { overflow-x: auto; }

.defilement-tableau:focus-visible {
  outline: 2px solid #0056b3;
  outline-offset: 2px;
}

Et les contre-exemples qui concentrent l'essentiel des non-conformités de la thématique 5 :

<!-- À ne pas faire : un titre au-dessus au lieu d'un caption.
     Le <h2> n'est associé à rien : le tableau est annoncé
     « tableau, 3 colonnes, 4 lignes », sans titre (critère 5.4). -->
<h2>Chiffre d'affaires par région</h2>
<table>
  <tr><th scope="col">Région</th></tr>
</table>

<!-- À ne pas faire : des en-têtes de ligne en <td>.
     LE défaut de la thématique 5 : en traversant la ligne, le lecteur
     d'écran annonce « 2,4 M€, +12 % »... de quoi ? -->
<tr>
  <td>Europe</td>
  <td>2,4 M€</td>
</tr>

<!-- À ne pas faire : une cellule d'angle vide dans la ligne d'en-têtes.
     La colonne des en-têtes de ligne n'a pas de nom. Si le design
     l'exige vide, y placer un texte masqué visuellement. -->
<th scope="col"></th>
<!-- À faire dans ce cas : -->
<th scope="col"><span class="sr-only">Région</span></th>

<!-- À ne pas faire : un tableau de mise en page avec du balisage de
     tableau de données (critère 5.8). S'il s'agit vraiment de mise en
     page : role="presentation", et mieux, CSS grid. -->
<table>
  <caption>Mise en page</caption>
  <tr><th>Barre latérale</th><td>Contenu principal</td></tr>
</table>

<!-- À ne pas faire : un conteneur défilant sans tabindex.
     Molette et doigt défilent, le clavier jamais : les colonnes de
     droite sont inatteignables (critère 10.11). -->
<div style="overflow-x: auto">
  <table>...</table>
</div>

Défauts fréquents et impact utilisateur

  • En-têtes de ligne en <td> : le défaut le plus répandu de la thématique 5. En traversant une ligne, le lecteur d'écran annonce « 2,4 M€, +12 % » sans jamais rattacher la région : les en-têtes de colonne seuls font la moitié du travail (critères 5.6 et 5.7).
  • Un titre au-dessus du tableau au lieu d'un <caption> : le tableau est annoncé « tableau, 3 colonnes, 4 lignes » sans titre ; dans une page à plusieurs tableaux, impossible de les distinguer sans les parcourir (critère 5.4).
  • <th> sans scope sur un tableau à double entrée : le navigateur devine les associations et se trompe dès que le tableau n'est pas trivial ; les cellules sont annoncées avec les mauvais en-têtes (critère 5.7).
  • scope conservé sur un tableau complexe à en-têtes fusionnés : les associations sont fausses avec assurance, ce qui est pire qu'absentes ; il faut headers/id (critère 5.7).
  • Cellule d'angle vide dans la ligne d'en-têtes : la colonne des en-têtes de ligne n'a pas de nom.
  • Conteneur défilant sans tabindex : l'utilisateur au clavier n'a aucun moyen d'atteindre les colonnes hors écran (critère 10.11).

Ce que les outils automatiques ne détectent pas

  • Des en-têtes de ligne balisés <td> : c'est du HTML parfaitement valide, seule la lecture humaine voit qu'il s'agissait d'en-têtes.
  • La pertinence du titre (critère 5.5) et celle du résumé d'un tableau complexe (critère 5.2) : un <caption> vide de sens passe tous les contrôles syntaxiques.
  • Des associations headers/id syntaxiquement correctes mais sémantiquement fausses : la cellule reliée aux mauvais en-têtes ne se voit qu'à la lecture.

La thématique 5 est par ailleurs l'une des mieux couvertes par les outils automatiques, dont notre scanner : <th> sans scope, <caption> mal placé ou éléments de tableau de données dans un tableau de présentation sont détectables. Bonne première passe, qui laisse entiers les trois angles morts ci-dessus.

Vérifier ce composant

Protocole manuel rapide, dans cet ordre :

  1. Le test des en-têtes de ligne, celui que tout le monde rate : au lecteur d'écran, se placer sur une cellule au milieu du tableau. Elle doit annoncer SES DEUX en-têtes : « Europe, Chiffre d'affaires, 2,4 M€ ». Si seul l'en-tête de colonne est annoncé, les en-têtes de ligne sont des <td>.
  2. Le test du titre : le tableau doit s'annoncer avec son titre. « Tableau » tout court signifie <caption> absent ou remplacé par un simple titre au-dessus.
  3. Le test des 320 px (critère 10.11) : réduire la fenêtre à 320 px de large. Si la page entière défile horizontalement, le tableau doit être enveloppé dans un conteneur défilant ; puis vérifier au clavier que Tab atteint ce conteneur et que les flèches le font défiler.
  4. Balayage automatique en complément, pour les scope manquants et les <caption> mal placés.

Deux outils gratuits du site aident à ce contrôle : le Simulateur Lecteur d'Écran montre l'arbre d'accessibilité du tableau (titre, en-têtes de colonnes et de lignes réellement exposés), et l'outil Résoudre un critère RGAA fournit pour chaque critère de la thématique 5 un exemple conforme à copier et le guide associé.

Approfondir avec les fiches critères

Vérifier ce composant sur votre site ?

Le scan repère les défauts détectables automatiquement (rôles incohérents, champs sans étiquette, attributs ARIA orphelins) ; le reste se vérifie à la main avec les protocoles de cette fiche.

Lancer un scan gratuit

Toutes les fiches composants accessibles