Normes · ARIA

Rôle Widget composite

menu

Marque un conteneur comme un menu applicatif — le popup de menus de style Fichier/Édition ou de menus contextuels. Il n'existe pas d'équivalent HTML. La liste de navigation d'un site n'est PAS un menu ; utilisez <nav> avec <ul> de liens à la place.

Quand l’utiliser

Pour un menu de style applicatif — le popup qui apparaît depuis un bouton « Fichier » ou un menu contextuel au clic droit, avec navigation par flèches et fermeture par Échap. Les enfants doivent être de type role="menuitem", role="menuitemcheckbox", role="menuitemradio" ou role="separator".

Le rôle menu relève de la sémantique applicative. La plus grande erreur sur le web est d’utiliser role="menu" pour la navigation d’un site, ce qui piège les utilisateurs clavier dans une navigation par flèches, annonce incorrectement les liens comme des éléments de menu, et brise le modèle mental de l’utilisateur.

Règle pratique : si le déclencheur est un hyperlien et que les éléments sont des hyperliens, il s’agit d’une navigation, pas d’un menu. Utilisez <nav> et <ul>.

Un menu DOIT avoir un nom accessible — utilisez aria-label ou aria-labelledby pointant vers le déclencheur.

Contrat clavier + focus

Conformément au modèle APG menu :

  • Le bouton déclencheur a aria-haspopup="menu" et aria-expanded. L’activation du déclencheur ouvre le menu et déplace le focus sur le premier menuitem.
  • Dans le menu : les flèches Haut/Bas déplacent le focus entre les éléments ; Début/Fin sautent au premier/dernier.
  • La flèche Droite ouvre un sous-menu (si l’élément ciblé en a un) ; la flèche Gauche revient au menu parent.
  • Entrée ou Espace active l’élément ciblé et ferme le menu.
  • Échap ferme le menu et renvoie le focus vers le déclencheur.
  • Anticipation de frappe : taper une lettre saute au prochain élément commençant par cette lettre.

Point d’arrêt tabulation unique : un seul menuitem à la fois a tabindex="0" ; les autres ont -1.

Erreurs courantes

  • role="menu" sur un élément <nav>. La sémantique applicative remplace la sémantique de navigation — les lecteurs d’écran cessent de l’annoncer comme un point de repère de navigation.
  • Menu sans aria-haspopup="menu" associé sur son déclencheur.
  • Échap ferme le menu mais ne renvoie pas le focus vers le déclencheur, laissant l’utilisateur sans repère.
  • Le focus ne se déplace PAS vers le premier menuitem à l’ouverture du menu — les utilisateurs doivent utiliser Tab dans le vide.
  • Sous-menus qui s’ouvrent au survol uniquement, pas au clavier.

Exemple

<button id="actions" aria-haspopup="menu" aria-expanded="false" aria-controls="actionsMenu">
  Actions
</button>
<ul id="actionsMenu" role="menu" aria-labelledby="actions" hidden>
  <li role="menuitem" tabindex="0">Edit</li>
  <li role="menuitem" tabindex="-1">Duplicate</li>
  <li role="separator"></li>
  <li role="menuitem" tabindex="-1">Delete</li>
</ul>