Normes · ARIA

Rôle Widget

button

Marque un élément comme bouton — un contrôle qui déclenche une action à l'activation. Préférez toujours l'élément natif <button> ; n'utilisez role="button" sur un <div> ou <span> que lorsque l'élément natif est impossible.

Quand l’utiliser

Presque jamais — utilisez l’élément natif <button>. L’élément natif gère gratuitement le focus, l’activation par les touches Espace et Entrée, l’état désactivé et la sémantique de soumission de formulaire. Recourir à role="button" sur un <div> signifie devoir réimplémenter tout cela, et la plupart des auteurs ne le font pas correctement.

Les cas légitimes pour role="button" sont restreints :

  • Vous êtes contraint par un système de design tiers qui livre des composants sans <button>.
  • Vous rédigez dans un environnement où <button> n’est pas disponible (certains gabarits CMS anciens).
  • Vous améliorez un <div> pour l’accessibilité à court terme, en attendant une refactorisation.

Si vous utilisez role="button", vous devez également :

  • Rendre l’élément focalisable avec tabindex="0".
  • Câbler keydown pour Enter et Space (avec event.preventDefault() sur Space pour éviter le défilement de la page).
  • Gérer vous-même l’état désactivé via aria-disabled="true" et empêcher les gestionnaires de clic de se déclencher.

Boutons bascule

Si le bouton est un bascule (muet / sonore, lecture / pause, suivre / ne plus suivre), définissez aria-pressed à "true" ou "false". Les lecteurs d’écran annoncent l’état avec le libellé : « Muet, bouton bascule, non activé ».

Erreurs fréquentes

  • <div onclick="…">Envoyer</div> — non focalisable, inutilisable au clavier, sans rôle. Les utilisateurs de souris peuvent s’en servir ; personne d’autre ne peut.
  • <a href="#" onclick="…"> faisant passer un lien pour un bouton. Le navigateur le traite comme un lien, le lecteur d’écran l’annonce comme un lien, l’utilisateur s’attend à une navigation.
  • role="button" sans tabindex="0" — le lecteur d’écran annonce « bouton » mais le clavier ne peut pas l’atteindre.
  • Des boutons personnalisés qui répondent à Entrée mais pas à Espace.
  • Des boutons sans nom accessible — les boutons icône seuls dépourvus de aria-label constituent l’erreur la plus fréquente qu’axe-core détecte.

Exemple

<!-- Préféré -->
<button type="button" aria-pressed="false">Mute</button>

<!-- Uniquement quand <button> est impossible -->
<div
  role="button"
  tabindex="0"
  aria-pressed="false"
  onclick="toggleMute()"
  onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); toggleMute(); }"
>
  Mute
</div>