Aller au contenu principal
Technique26 janvier 20268 min

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.
NavigationARIAClavierRGAA

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

CODE
<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 navigation
  • aria-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é :

CODE
<!-- 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 :

CODE
<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 :

CODE
<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

ToucheAction
TabPasse à l'élément focusable suivant
Shift + TabPasse à l'élément focusable précédent
Entrée/EspaceOuvre/ferme le sous-menu (sur le bouton)
ÉchapFerme 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.

CODE
// À 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 :

CODE
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 :

CODE
<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 :

CODE
<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

CODE
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 :

  1. Navigation clavier : Parcourez entièrement le menu avec Tab seul
  2. Lecteur d'écran : Testez avec NVDA ou VoiceOver
  3. Focus visible : Vérifiez que chaque élément focusable est clairement identifiable
  4. 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.

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.