WAI-ARIA — Web Accessibility Initiative Accessible Rich Internet Applications — est une spécification du W3C publiée en 2008 et régulièrement mise à jour (version 1.2 en 2023). Elle définit un ensemble d’attributs HTML qui permettent de communiquer aux technologies d’assistance des informations que le HTML seul ne peut pas exprimer.
Avant d’apprendre les attributs, il faut comprendre pourquoi ARIA existe et ce qu’il ne fait pas. C’est là que la plupart des erreurs trouvent leur origine.
Pourquoi ARIA existe
Le HTML sémantique a été conçu pour des documents. Un <h2>, un <p>, un <a> — ces éléments décrivent la structure d’un texte. Mais les interfaces web modernes sont des applications, pas des documents. Un menu déroulant, une boîte de dialogue, un curseur de volume, un fil d’étapes — HTML n’a pas de balise native pour ces composants.
Les lecteurs d’écran interprètent le HTML pour construire une représentation de la page appelée arbre d’accessibilité. Quand un composant est construit avec des <div> et du JavaScript, l’arbre d’accessibilité ne voit qu’une boîte vide sans nom, sans rôle, sans état. L’utilisateur de lecteur d’écran arrive dans un néant.
ARIA comble ce vide en ajoutant trois types d’informations :
- Le rôle : ce qu’est l’élément (
role="button",role="dialog",role="tab") - Les propriétés : ses caractéristiques permanentes (
aria-label,aria-required,aria-haspopup) - Les états : sa condition actuelle, changeante (
aria-expanded,aria-checked,aria-disabled)
Ces trois informations alimentent l’arbre d’accessibilité et permettent aux technologies d’assistance d’annoncer le composant correctement.
Ce qu’ARIA ne fait pas
C’est le point le plus important, et le moins souvent enseigné.
ARIA ne donne pas de comportement. Ajouter role="button" sur un <div> annonce “bouton” au lecteur d’écran. Mais si ce <div> n’est pas focusable et ne réagit pas à la touche Entrée, l’utilisateur de clavier ne peut pas l’activer. ARIA a menti : il a promis un bouton, mais le bouton est cassé.
ARIA ne remplace pas le HTML sémantique. Un <div role="list"> avec des <div role="listitem"> est plus fragile qu’un <ul> avec des <li>. Le HTML natif vient avec des comportements, des styles par défaut, et une compatibilité AT testée depuis des décennies.
ARIA ne répare pas ce qui est invisible. Un élément avec display:none ou visibility:hidden est retiré de l’arbre d’accessibilité. Ajouter aria-live sur son parent ne changera rien — l’AT ne le verra toujours pas.
ARIA est un outil de communication, pas de création. Il décrit ce qui existe. Il ne crée pas ce qui manque.
Les 3 règles d’or
Le W3C a publié cinq règles d’utilisation d’ARIA. En pratique, trois d’entre elles couvrent 95% des situations réelles.
Règle 1 — N’utilise pas ARIA si HTML suffit
Si un élément HTML natif existe pour ce que tu veux faire, utilise-le. Toujours.
<!-- ✗ ARIA inutile — <button> fait déjà tout ça -->
<div role="button" tabindex="0" onclick="...">
Envoyer
</div>
<!-- ✓ HTML natif — focus, clavier, annonce AT gratuits -->
<button type="button" onclick="...">
Envoyer
</button>
Ce que <button> apporte gratuitement :
- Focusable au clavier sans
tabindex - Activable avec Entrée et Espace
- Annoncé “bouton” par tous les lecteurs d’écran
- Désactivable avec l’attribut
disabled - Stylisable en CSS
La liste des éléments HTML qui remplacent l’ARIA est longue : <a>, <button>, <input>, <select>, <textarea>, <details>, <summary>, <nav>, <main>, <header>, <footer>, <aside>, <section>, <article>, <h1>-<h6>, <ul>, <ol>, <table>.
En audit, cette règle permet d’identifier les cas où ARIA est utilisé pour compenser du HTML non sémantique — souvent signe d’un problème plus profond dans la structure.
Règle 2 — Ne cache pas ce qui doit être utilisable
aria-hidden="true" retire un élément de l’arbre d’accessibilité. Si cet élément est focusable (lien, bouton, input), l’utilisateur de clavier peut l’atteindre, mais le lecteur d’écran n’annonce rien. C’est un piège silencieux.
<!-- ✗ Catastrophe : le lien est focusable mais invisible pour le lecteur d'écran -->
<nav aria-hidden="true">
<a href="/accueil">Accueil</a>
<a href="/contact">Contact</a>
</nav>
<!-- ✗ Même problème sur un bouton -->
<button aria-hidden="true">Fermer</button>
<!-- ✓ aria-hidden uniquement sur les éléments décoratifs non interactifs -->
<svg aria-hidden="true" focusable="false">...</svg>
<span class="icone-decorative" aria-hidden="true">★</span>
La règle est simple : aria-hidden="true" ne doit jamais être appliqué sur un élément focusable, ni sur un ancêtre d’un élément focusable.
Si tu veux masquer visuellement un élément tout en le gardant accessible aux AT, utilise une classe sr-only (visible uniquement par les AT). Si tu veux le masquer aux AT tout en le gardant visible, utilise aria-hidden="true" — mais jamais sur quelque chose d’interactif.
Règle 3 — ARIA décrit, toi tu implémentes le comportement
Quand tu ajoutes un rôle de widget interactif, tu t’engages à implémenter le comportement clavier correspondant. Le W3C documente ce comportement dans les ARIA Authoring Practices Guide (APG).
<!-- role="button" engage à implémenter : -->
<!-- - tabindex="0" pour la focusabilité -->
<!-- - keydown Enter → déclenche l'action -->
<!-- - keydown Space → déclenche l'action -->
<div
role="button"
tabindex="0"
onclick="fermer()"
onkeydown="if(e.key==='Enter'||e.key===' ')fermer()"
>
Fermer
</div>
<!-- Mais pourquoi ne pas simplement écrire : -->
<button type="button" onclick="fermer()">Fermer</button>
Les rôles de widget les plus courants et leur comportement clavier attendu :
| Rôle | Touches clavier requises |
|---|---|
button | Entrée, Espace |
checkbox | Espace (toggle) |
combobox | Flèches, Entrée, Échap |
dialog | Échap (fermeture), focus piégé à l’intérieur |
menu / menuitem | Flèches, Entrée, Échap |
tab | Flèches gauche/droite entre onglets |
slider | Flèches, Page Up/Down, Home, End |
Négliger le comportement clavier est l’erreur la plus fréquente sur les composants ARIA personnalisés.
Ce que le lecteur d’écran annonce
Pour chaque élément, un lecteur d’écran annonce généralement :
[Nom] [Rôle] [État] [Description]
- Nom : le texte visible, l’
aria-label, ou le texte référencé pararia-labelledby - Rôle : “bouton”, “lien”, “case à cocher”, “boîte de dialogue”…
- État : “coché”, “réduit”, “désactivé”, “requis”…
- Description : le texte référencé par
aria-describedby(souvent les messages d’aide)
Exemples d’annonces NVDA sur Firefox :
<button aria-expanded="false" aria-controls="menu">
Menu principal
</button>
→ "Menu principal, bouton réduit"
<input type="checkbox" checked aria-label="Accepter les conditions">
→ "Accepter les conditions, case à cocher cochée"
<a href="/contact" aria-current="page">
Contact
</a>
→ "Contact, page actuelle, lien"
Ces annonces varient selon le lecteur d’écran, le navigateur, et les paramètres utilisateur. C’est pourquoi tester avec un vrai lecteur d’écran reste indispensable — aucun outil automatique ne peut simuler fidèlement ce qu’un utilisateur entend.
Critères RGAA directement liés
Les critères RGAA qui s’appuient sur une utilisation correcte d’ARIA :
- 7.1 : Chaque script est-il, si nécessaire, compatible avec les technologies d’assistance ?
- 7.2 : Chaque script a-t-il, si nécessaire, une alternative ?
- 7.3 : Chaque script est-il contrôlable par le clavier ?
- 9.2 : La structure du document est-elle cohérente ? (landmarks ARIA)
- 12.6 : Les zones de regroupement peuvent-elles être atteintes ou évitées ? (landmarks)
Les articles suivants de cette série détaillent les critères RGAA pour chaque famille d’attributs ARIA.
Pour aller plus loin
- Spécification WAI-ARIA 1.2 lien externe qui s'ouvre dans un nouvel onglet : référence normative
- ARIA Authoring Practices Guide lien externe qui s'ouvre dans un nouvel onglet : patterns et comportements clavier
- a11ysupport.io lien externe qui s'ouvre dans un nouvel onglet : support réel par AT et navigateur