Menus déroulants accessibles : Guide technique complet
En Bref : L'essentiel à retenir
- Les menus déroulants doivent s'ouvrir au clic ou à la touche Entrée, jamais automatiquement au focus pour ne pas piéger les utilisateurs clavier.
- L'attribut aria-expanded indique l'état du sous-menu, aria-haspopup signale sa présence aux technologies d'assistance.
- La touche Échap doit permettre de fermer le menu et la touche Tab ne doit pas forcer le parcours de tous les sous-éléments.
- Le HTML sémantique (nav, ul, li) est essentiel avant d'ajouter des attributs ARIA pour la compatibilité avec les lecteurs d'écran.
Les menus déroulants sont omniprésents sur le web, mais ils constituent l'un des composants les plus problématiques en matière d'accessibilité. Entre pièges au clavier, sous-menus invisibles pour les lecteurs d'écran et ouvertures intempestives, les pièges sont nombreux. Voici comment créer des menus déroulants véritablement accessibles.
Pourquoi les menus déroulants posent problème
Les menus de navigation avec sous-menus représentent un défi d'accessibilité majeur pour plusieurs raisons :
- Les utilisateurs clavier peuvent se retrouver "piégés" dans des sous-menus
- Les lecteurs d'écran ont du mal à percevoir la structure hiérarchique
- L'ouverture au survol exclut les utilisateurs tactiles et clavier
- La navigation peut devenir laborieuse avec de nombreux éléments
[!NOTE] Le RGAA traite les menus de navigation dans plusieurs critères, notamment le critère 12.1 sur les systèmes de navigation et le critère 7.1 sur les scripts accessibles.
Structure HTML sémantique : la base indispensable
Avant d'ajouter des attributs ARIA, assurez-vous que votre structure HTML est sémantique et logique.
Exemple de structure correcte
<nav aria-label="Navigation principale">
<ul>
<li>
<a href="/accueil">Accueil</a>
</li>
<li>
<button aria-expanded="false" aria-haspopup="true">
Produits
<span aria-hidden="true">▼</span>
</button>
<ul>
<li><a href="/produits/categorie-1">Catégorie 1</a></li>
<li><a href="/produits/categorie-2">Catégorie 2</a></li>
</ul>
</li>
<li>
<a href="/contact">Contact</a>
</li>
</ul>
</nav>
Points essentiels de la structure
<nav>: Balise sémantique identifiant une zone de navigationaria-label: Nomme la navigation (utile quand plusieurs navs existent)<ul>et<li>: Liste non ordonnée pour la structure hiérarchique- Séparation fonction/navigation : Bouton pour ouvrir, liens pour naviguer
Les attributs ARIA indispensables
aria-expanded : l'indicateur d'état
Cet attribut signale aux technologies d'assistance si le sous-menu est ouvert ou fermé :
<!-- Menu fermé -->
<button aria-expanded="false">Produits</button>
<!-- Menu ouvert -->
<button aria-expanded="true">Produits</button>
Mettez à jour cette valeur dynamiquement via JavaScript lors de l'ouverture/fermeture.
aria-haspopup : l'indicateur de présence
Cet attribut prévient l'utilisateur qu'un élément déclenchera l'apparition d'un contenu supplémentaire :
<button aria-haspopup="true" aria-expanded="false">
Menu avec sous-menu
</button>
[!TIP] N'utilisez PAS
role="menu"pour les menus de navigation classiques. Ce rôle est destiné aux menus applicatifs (comme dans une barre d'outils) et implique une navigation par flèches directionnelles que la plupart des menus web n'implémentent pas correctement.
aria-current : l'indicateur de page active
Pour indiquer la page courante dans la navigation :
<a href="/produits" aria-current="page">Produits</a>
Gestion de la navigation clavier
La navigation clavier est critique pour l'accessibilité des menus déroulants.
Comportement attendu
| Touche | Action |
|---|---|
| Tab | Passe à l'élément focusable suivant |
| Shift + Tab | Passe à l'élément focusable précédent |
| Entrée/Espace | Ouvre/ferme le sous-menu (sur le bouton) |
| Échap | Ferme le sous-menu ouvert |
Erreur fréquente : ouverture au focus
Ne jamais ouvrir un sous-menu automatiquement quand un élément reçoit le focus. Si le menu s'ouvre au focus, l'utilisateur clavier devra parcourir tous les sous-éléments avant d'atteindre l'élément de navigation suivant.
// À NE PAS FAIRE
button.addEventListener('focus', () => {
openSubmenu(); // Piège l'utilisateur !
});
// BONNE PRATIQUE
button.addEventListener('click', () => {
toggleSubmenu();
});
button.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggleSubmenu();
}
});
Fermeture avec la touche Échap
Permettez toujours la fermeture du menu avec Échap :
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && menuIsOpen) {
closeSubmenu();
triggerButton.focus(); // Retour au bouton déclencheur
}
});
Le dilemme des liens avec double fonction
Comment gérer un élément de menu principal qui est à la fois un lien ET un déclencheur de sous-menu ? C'est l'un des problèmes les plus épineux.
Solution 1 : Séparer les fonctions
La meilleure approche est de séparer clairement le lien et le bouton d'expansion :
<li>
<a href="/produits">Produits</a>
<button aria-expanded="false" aria-label="Afficher le sous-menu Produits">
<span aria-hidden="true">▼</span>
</button>
<ul hidden><!-- sous-menu --></ul>
</li>
Solution 2 : Lien principal, bouton sur mobile
Sur desktop, le lien principal fonctionne normalement et le survol affiche le sous-menu. Sur mobile, un bouton dédié gère l'ouverture.
Indicateurs visuels essentiels
Flèche indicatrice
Ajoutez une flèche pour signaler la présence d'un sous-menu :
<button aria-expanded="false">
Produits
<svg aria-hidden="true" class="icon-chevron"><!-- ... --></svg>
</button>
Changez l'orientation de la flèche selon l'état (vers le bas = fermé, vers le haut = ouvert).
Focus visible
Assurez un indicateur de focus clairement visible sur tous les éléments interactifs. Consultez notre générateur de focus ring pour créer des styles conformes.
Contraste du sous-menu
Le sous-menu doit avoir un contraste suffisant avec l'arrière-plan de la page pour être clairement perçu comme distinct.
Gestion du survol et du tactile
Survol : avec précaution
Si vous implémentez l'ouverture au survol pour les utilisateurs souris :
- Ajoutez un délai avant l'ouverture (environ 300ms) pour éviter les ouvertures accidentelles
- Ajoutez un délai avant la fermeture pour permettre le déplacement vers le sous-menu
- Conservez l'ouverture tant que le curseur reste sur le menu ou le sous-menu
Écrans tactiles
Le survol n'existe pas sur tactile. Prévoyez systématiquement une alternative :
- Le premier tap ouvre le sous-menu
- Le second tap sur un lien navigue
Ou mieux : utilisez des boutons dédiés pour l'ouverture.
Exemple complet en JavaScript
class AccessibleDropdown {
constructor(menuItem) {
this.menuItem = menuItem;
this.button = menuItem.querySelector('[aria-expanded]');
this.submenu = menuItem.querySelector('ul');
this.init();
}
init() {
this.button.addEventListener('click', () => this.toggle());
// Fermeture avec Échap
this.menuItem.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.close();
this.button.focus();
}
});
// Fermeture au clic extérieur
document.addEventListener('click', (e) => {
if (!this.menuItem.contains(e.target)) {
this.close();
}
});
}
toggle() {
const isOpen = this.button.getAttribute('aria-expanded') === 'true';
isOpen ? this.close() : this.open();
}
open() {
this.button.setAttribute('aria-expanded', 'true');
this.submenu.hidden = false;
}
close() {
this.button.setAttribute('aria-expanded', 'false');
this.submenu.hidden = true;
}
}
Test et validation
Pour vérifier l'accessibilité de vos menus :
- Navigation clavier : Parcourez entièrement le menu avec Tab seul
- Lecteur d'écran : Testez avec NVDA ou VoiceOver
- Focus visible : Vérifiez que chaque élément focusable est clairement identifiable
- Annonces : Vérifiez que l'état ouvert/fermé est bien annoncé
Lancez un audit RGAA complet pour identifier d'autres problèmes d'accessibilité potentiels sur votre navigation.
Conclusion
Créer des menus déroulants accessibles demande une attention particulière à la structure HTML, aux attributs ARIA et surtout à l'expérience clavier. En suivant ces bonnes pratiques, vous garantissez que tous vos utilisateurs pourront naviguer efficacement sur votre site.
L'accessibilité des menus n'est pas qu'une contrainte technique : c'est une opportunité d'améliorer l'expérience utilisateur pour tous, y compris les utilisateurs de souris qui bénéficient d'interactions plus claires et prévisibles.
Guides RGAA associés
Pour aller plus loin sur les sujets abordés dans cet article, consultez nos fiches techniques :
Chaque champ de formulaire doit avoir une étiquette (label) qui lui est liée explicitement.
Chaque image porteuse d'information doit avoir une alternative textuelle pertinente via l'attribut alt. Les images décoratives doivent avoir un attribut alt vide.
Dans chaque page web, un lien d'évitement ou d'accès rapide au contenu principal doit être présent, visible au focus, et placé en premier élément focusable.
Articles similaires
Votre site est-il conforme ?
Ne prenez pas de risques avec l'accessibilité. Lancez un audit complet de votre site en quelques minutes et obtenez un rapport détaillé des corrections à apporter.