Nom, rôle, valeur
Chaque composant d'interface doit exposer programmatiquement un nom, un rôle et — le cas échéant — une valeur et un état. Sans cela, les lecteurs d'écran, la commande vocale et les dispositifs à contacteur ne peuvent ni identifier ni actionner le contrôle.
Ce que ce critère demande
Chaque élément interactif de la page — boutons, liens, champs de formulaire, onglets, curseurs, widgets personnalisés — doit exposer trois informations aux technologies d’assistance :
- Nom — comment ce contrôle s’appelle-t-il ? (« Envoyer », « Fermer la boîte de dialogue », « Volume »)
- Rôle — de quel type de contrôle s’agit-il ? (bouton, lien, case à cocher, onglet, curseur)
- Valeur / état — pour les composants qui en ont un : est-il activé, développé, coché, sélectionné ? Quelle est la valeur actuelle ?
Cette exposition doit être programmatique — définie dans le DOM, non peinte par CSS. Les lecteurs d’écran, les plages braille, les logiciels de commande vocale et les scanners à contacteur lisent tous l’arbre d’accessibilité, pas les pixels.
Comment le satisfaire
- Utiliser l’élément HTML natif chaque fois qu’il en existe un.
<button>est livré avec le rôle correct, le focus, la gestion du clavier et un nom accessible tiré de son contenu textuel — gratuitement. - Pour les boutons avec icône seule, ajouter un
aria-label(ou du texte masqué visuellement).<button aria-label="Fermer">×</button>. - Pour les champs de formulaire, associer un
<label for>avec l’iddu champ. Ou envelopper le champ à l’intérieur du<label>. Le texte de l’attributplaceholdern’est pas un label. - Lorsqu’un widget personnalisé doit être construit avec
<div>et<span>, ajouterrole="…", gérertabindex, gérer les touches Entrée et Espace, et refléter l’état avecaria-pressed,aria-expanded,aria-checked,aria-selected,aria-valuenow. - Passer la page rendue dans l’inspecteur d’arbre d’accessibilité du navigateur (Chrome DevTools → Éléments → Accessibilité) et lire chaque contrôle : chacun doit être annoncé sous la forme nom + rôle + état.
Échecs courants
<div onclick="…">mis en forme comme un bouton — pas de rôle, pas de clavier, pas de nom. Les lecteurs d’écran l’ignorent. La commande vocale ne peut pas dire « cliquer sur Enregistrer ».<div role="button">sanstabindex="0", sans gestionnaire Entrée/Espace — semble accessible, ne l’est pas.- Les boutons avec icône seule (
<button><svg /></button>) sansaria-label,aria-labelledbyni texte masqué visuellement. Annoncés comme simple « bouton ». - Les listes déroulantes personnalisées construites avec
<div>et JavaScript, manquant derole="combobox",aria-expanded,aria-controlset les rôles listbox/option sous-jacents. - Les boutons bascule (muet, favori, suivre) qui changent d’état visuellement mais ne mettent jamais à jour
aria-pressed. Les utilisateurs voyants voient le changement ; les utilisateurs de lecteurs d’écran n’entendent aucune différence. - Les champs de formulaire avec un label visuel adjacent mais sans lien
for/idou<label>englobant. - Les cases à cocher personnalisées dessinées avec
<svg>et un champ natif masqué qui ne reflète jamais:checkeddans l’interface visible — les états du lecteur d’écran et visuels divergent.
Pourquoi c’est important
Il s’agit du critère le plus cité dans la spécification. Presque chaque plainte du type « ce site est inutilisable avec un lecteur d’écran » se résout en un échec 4.1.2 quelque part — généralement un <div> qui se fait passer pour un bouton, ou un bouton avec icône sans nom. C’est aussi là qu’apparaît le coût de la construction de widgets personnalisés : chaque contrôle HTML natif satisfait déjà 4.1.2 ; chaque widget <div> fait maison doit le mériter ligne par ligne. L’audit 4.1.2 le plus rapide consiste à naviguer au clavier sur la page avec un lecteur d’écran et écouter — tout ce qui s’annonce comme « vide » ou simplement « bouton » est un problème à corriger.