# Ajouter un indicateur d’étape accessible à un menu de restaurant

> Entrée, plat, dessert : comment construire un indicateur de progression annoncé correctement aux lecteurs d'écran sur la page de menu d'un restaurant.

- Auteur : WordPress Développement
- Publié le : 2022-04-03
- Mis à jour le : 2022-04-03
- Catégorie : Accessibilité
- URL : https://www.wpmoderne.fr/accessibilite/indicateur-etape-accessible-menu-restaurant/

## L’essentiel

- Structure sémantique avant tout effet visuel
- Annonce du service actif via aria-current
- Test au clavier et au lecteur d'écran

Comment annoncer à une personne malvoyante quel service du menu — entrée, plat ou dessert — est actuellement affiché, sans dupliquer l'information trois fois dans le code ? C'est la question posée par la refonte de la page de menu d'un restaurant gastronomique qui souhaitait remplacer ses onglets visuels par quelque chose de plus lisible, sans repartir d'une extension tierce.

L'indicateur d'étape visuel — trois pastilles reliées par un trait, la pastille active mise en évidence — est un classique du web. Son défaut le plus courant : toute l'information repose sur la couleur et la position, deux signaux invisibles pour un lecteur d'écran. La solution ne demande ni bibliothèque JavaScript ni extension : une liste ordonnée, un attribut `aria-current`, et une structure de titres cohérente suffisent.

## Étape 1 : poser la structure sémantique

Avant tout style, l'indicateur doit exister comme une liste ordonnée classique. Cela garantit qu'un lecteur d'écran annonce « liste de 3 éléments » et permet de se déplacer d'un élément à l'autre avec les raccourcis de navigation par liste :

```
<nav aria-label="Étapes du menu">
  <ol class="menu-etapes">
    <li><a href="#entree">Entrée</a></li>
    <li><a href="#plat" aria-current="step">Plat</a></li>
    <li><a href="#dessert">Dessert</a></li>
  </ol>
</nav>
```

La valeur `step` de l'attribut `aria-current` est justement prévue par la spécification WAI-ARIA pour ce cas d'usage : elle indique qu'un élément représente l'étape courante dans un processus séquentiel, à distinguer de `aria-current="page"` réservé à la navigation entre pages.

## Étape 2 : synchroniser le style sur l'état, pas l'inverse

> L'essentiel à retenir : Structure sémantique avant tout effet visuel ; Annonce du service actif via aria-current ; Test au clavier et au lecteur d'écran

L'erreur fréquente consiste à poser une classe CSS pour l'effet visuel, puis à oublier l'attribut ARIA correspondant. Il faut inverser l'ordre de dépendance : c'est l'attribut `aria-current` qui pilote le style, jamais l'inverse.

```
.menu-etapes a[aria-current="step"] {
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
}
```

Ce sélecteur CSS garantit qu'il est impossible d'avoir un style « actif » sans l'annonce correspondante pour les technologies d'assistance : les deux sont techniquement liés par construction.

## Étape 3 : gérer le changement d'étape au clic ou au défilement

Si le menu se découpe en sections d'une seule page avec défilement, un petit script suffit pour déplacer l'attribut `aria-current` au bon endroit lors du changement de section visible :

```
const sections = document.querySelectorAll('.menu-etapes a');
const observer = new IntersectionObserver((entries) => {
  entries.forEach((entree) => {
    if (entree.isIntersecting) {
      const cible = document.querySelector(
        `.menu-etapes a[href="#${entree.target.id}"]`
      );
      sections.forEach((lien) => lien.removeAttribute('aria-current'));
      if (cible) cible.setAttribute('aria-current', 'step');
    }
  });
}, { threshold: 0.6 });

document.querySelectorAll('main section[id]').forEach((s) => observer.observe(s));
```

L'utilisation d'un `IntersectionObserver` évite d'écouter l'évènement de défilement directement, ce qui économise des cycles de calcul et ne modifie l'attribut qu'au moment pertinent.

## Étape 4 : vérifier avec un lecteur d'écran

Le test se fait en trois minutes avec NVDA ou VoiceOver : on active la navigation par liste, on écoute l'annonce de chaque lien. Le résultat attendu ressemble à « Plat, lien, étape courante » plutôt qu'un simple « Plat, lien ». Si l'annonce ne mentionne pas l'étape courante, l'attribut n'est probablement pas positionné au bon moment du cycle de vie du composant.

- Vérifier que chaque lien reste atteignable au clavier avec `Tab` ;
- Vérifier que l'ordre de tabulation suit l'ordre visuel entrée, plat, dessert ;
- Vérifier qu'un seul élément à la fois porte `aria-current="step"`.

## En résumé

Un indicateur d'étape accessible ne demande ni animation compliquée ni bibliothèque externe. La combinaison d'une liste ordonnée, de `aria-current="step"` et d'un script minimal pour synchroniser l'état suffit à rendre l'information disponible à toutes les personnes qui consultent le menu, quel que soit leur mode de navigation.
