Retour au blog
août 2026·4 min de lectureGénéré par IA
Langue:DeutschEnglishFrançaisÖsterreichischKlingonian Version originale: English

Les bases de l'accessibilité web : ARIA sans deviner

#accessibility#html#frontend

L'erreur ARIA la plus courante n'est pas d'utiliser le mauvais attribut : c'est de recourir à ARIA tout court alors qu'un élément HTML natif aurait résolu le problème gratuitement. ARIA (Accessible Rich Internet Applications) existe pour décrire des widgets personnalisés pour lesquels HTML n'a pas d'élément intégré, pas pour rafistoler un <div> qui se fait passer pour un <button>. La première règle d'ARIA, directement tirée des auteurs de la spécification, est : n'utilisez pas ARIA si vous pouvez l'éviter.

Le problème du div-bouton

Cela revient constamment dans les bibliothèques de composants :

<div class="button" onclick="submitForm()">Submit</div>

Visuellement, c'est un bouton. Pour un lecteur d'écran, c'est un bloc de texte sans libellé et non interactif : on ne peut pas y accéder avec Tab, il n'est pas annoncé comme un bouton, on ne l'active pas avec Entrée ou Espace. On peut tout remettre avec ARIA et JavaScript :

<div
  class="button"
  role="button"
  tabindex="0"
  onclick="submitForm()"
  onkeydown="if (event.key === 'Enter' || event.key === ' ') submitForm()"
>
  Submit
</div>

Ou on peut utiliser l'élément qui fait déjà tout cela :

<button onclick="submitForm()">Submit</button>

Prise en charge du clavier, gestion du focus, nom accessible, bon rôle : tout est gratuit, cohérent dans tous les navigateurs et lecteurs d'écran, sans une ligne de JavaScript. C'est le réflexe à intérioriser : recourez d'abord à <button>, <a href>, <input>, <select> et leurs semblables, et ne sortez de la sémantique native de HTML que lorsque vous construisez quelque chose pour lequel HTML n'a réellement aucun élément, comme un panneau d'onglets ou une zone combinée avec autocomplétion.

Quand ARIA mérite sa place : l'étiquetage

Même avec des éléments natifs, certaines choses demandent un contexte supplémentaire que le texte visible ne transmet pas. Un bouton avec seulement une icône en est le cas classique :

<button aria-label="Close dialog">
  <svg><!-- X icon --></svg>
</button>

Sans aria-label, un lecteur d'écran l'annonce simplement comme « bouton » : techniquement atteignable et activable, mais l'utilisateur ignore ce qu'il fait. aria-label fournit un nom accessible quand aucun texte visible ne peut en servir. S'il existe un texte visible à proximité mais pas à l'intérieur du bouton lui-même, aria-labelledby le désigne par son identifiant au lieu de le dupliquer :

<h2 id="billing-heading">Billing Address</h2>
<button aria-labelledby="billing-heading">Edit</button>

Cela est annoncé « Modifier, Adresse de facturation » : plus utile qu'un simple « Modifier » quand une page contient cinq boutons de modification identiques pour cinq sections différentes.

Décrire l'état des widgets personnalisés

C'est là qu'ARIA fait un vrai travail porteur : les composants personnalisés doivent annoncer des changements d'état que les éléments natifs gèrent automatiquement. Une section repliable :

<button aria-expanded="false" aria-controls="panel-1" id="toggle-1">
  Show details
</button>
<div id="panel-1" hidden>
  ...
</div>
const toggle = document.getElementById('toggle-1');
const panel = document.getElementById('panel-1');

toggle.addEventListener('click', () => {
  const isExpanded = toggle.getAttribute('aria-expanded') === 'true';
  toggle.setAttribute('aria-expanded', String(!isExpanded));
  panel.hidden = isExpanded;
});

aria-expanded doit être maintenu synchronisé avec l'état visible réel en JavaScript : les attributs ARIA ne font jamais rien par eux-mêmes, ils sont purement informatifs pour les technologies d'assistance. Définissez aria-expanded="false" sans jamais le mettre à jour, et l'utilisateur d'un lecteur d'écran se verra indiquer que le panneau est replié pour toujours, même après qu'il l'a ouvert.

Régions dynamiques (live regions) pour les mises à jour dynamiques

Quand le contenu change sans navigation de page ni changement de focus (une erreur de validation de formulaire qui apparaît, un toast « enregistré », des résultats de recherche qui se mettent à jour), les utilisateurs voyants le voient se produire, mais un lecteur d'écran n'a aucune raison d'annoncer quelque chose en dehors du focus actuel de l'utilisateur, sauf si vous le lui dites.

<div aria-live="polite" id="save-status"></div>
document.getElementById('save-status').textContent = 'Changes saved.';

aria-live="polite" indique à la technologie d'assistance d'annoncer le changement une fois que l'utilisateur fait une pause dans ce qu'il fait : adapté aux messages d'état. N'utilisez aria-live="assertive" que pour ce qui doit vraiment interrompre, comme un avertissement d'expiration de session ; en abuser rend une page épuisante à utiliser avec un lecteur d'écran, puisque chaque petite mise à jour coupe ce qui était en cours de lecture.

La règle qui attrape le plus de bugs

Si vous ne retenez qu'une habitude : après avoir ajouté un role ou un attribut aria-*, demandez-vous quel élément natif aurait pu éviter ce besoin. role="button" sur un <div> → il aurait fallu un <button>. role="navigation" sur un conteneur générique → il aurait fallu un <nav>. aria-required="true" sur un champ texte → il aurait fallu l'attribut required, qui transmet la même chose à la technologie d'assistance et apporte en plus la validation gratuite du navigateur.

Ensuite, pour l'ARIA que vous conservez : passez-le une fois dans un lecteur d'écran. VoiceOver est fourni avec tous les Mac (Cmd+F5 pour l'activer) et NVDA est gratuit sous Windows. Cinq minutes à naviguer dans votre propre interface au clavier et à l'oreille attrapent plus de vrais problèmes que lire la spécification ARIA de bout en bout : vous remarquerez immédiatement un bouton à icône sans libellé ou une région dynamique qui ne se déclenche jamais, parce que ce sera vous qui serez déconcerté par le silence.

À retenir

ARIA complète la sémantique de HTML pour les cas que HTML ne couvre pas : il ne remplace pas le choix du bon élément au départ. Commencez par du HTML natif, ajoutez aria-label/aria-labelledby là où le nom accessible n'est pas évident d'après le texte visible, utilisez des attributs d'état comme aria-expanded seulement si vous les gardez aussi synchronisés avec la réalité, et réservez les régions dynamiques aux mises à jour qu'un utilisateur a vraiment besoin d'entendre en dehors de son focus actuel.

Plus récentÉcrire un outil en ligne de commande simple avec Node.jsPlus ancienGuide pratique des stratégies de branches Git