Normes · ARIA

Rôle Widget

radio

Marque un élément comme option unique dans un groupe mutuellement exclusif. Un radio DOIT se trouver dans un radiogroup (ou un fieldset natif). Utilisez <input type="radio"> en premier ; recourez à role="radio" uniquement lorsque l'élément natif est impossible.

Quand l’utiliser

Utilisez <input type="radio"> regroupés par un attribut name commun, enveloppés dans un <fieldset> avec un <legend>. L’élément natif gère la navigation par touches fléchées, le tabindex tournant, la sélection exclusive et la soumission du formulaire sans effort supplémentaire.

role="radio" est destiné aux composants personnalisés — contrôles segmentés, widgets de notation, sélecteurs thématiques — où vous ne pouvez pas utiliser l’élément natif. Un élément role="radio" DOIT avoir un parent (ou une cible aria-owns) avec role="radiogroup".

Contrat clavier et focus

Conformément au modèle de groupe radio APG :

  • Tab déplace le focus dans le groupe, vers le radio coché (ou le premier radio si aucun n’est coché).
  • Tab sort du groupe. Tab ne cycle PAS entre les radios.
  • Les touches fléchées (haut/bas ou gauche/droite) déplacent le focus vers le radio suivant/précédent ET le cochent. C’est inhabituel — la plupart des composants séparent le focus de la sélection, mais les radios les couplent.
  • Espace coche le radio ciblé s’il ne l’est pas déjà.

Utilisez un tabindex tournant : seul le radio actuellement sélectionné a tabindex="0", les autres ont tabindex="-1".

Échecs courants

  • Radios personnalisés où Tab cycle entre chaque option (au lieu des touches fléchées). Rompt le modèle d’interaction radio standard.
  • role="radio" sans role="radiogroup" enveloppant. Les lecteurs d’écran ne peuvent pas annoncer l’étiquette du groupe ni la position dans l’ensemble.
  • Tous les radios avec tabindex="0" — chaque radio entre dans l’ordre de tabulation, multipliant les frappes.
  • aria-checked absent au rendu initial.
  • Radios personnalisés qui se découlent lorsqu’on les presse à nouveau. Un radio est exclusif : une fois coché, la seule façon de le décocher est d’en cocher un autre dans le groupe.

Exemple

<!-- Préféré -->
<fieldset>
  <legend>Notification frequency</legend>
  <label><input type="radio" name="freq" value="daily" checked> Daily</label>
  <label><input type="radio" name="freq" value="weekly"> Weekly</label>
  <label><input type="radio" name="freq" value="never"> Never</label>
</fieldset>

<!-- Groupe radio personnalisé -->
<div role="radiogroup" aria-labelledby="freqLabel">
  <span id="freqLabel">Notification frequency</span>
  <div role="radio" aria-checked="true"  tabindex="0">Daily</div>
  <div role="radio" aria-checked="false" tabindex="-1">Weekly</div>
  <div role="radio" aria-checked="false" tabindex="-1">Never</div>
</div>