# Adapter un mega-menu existant pour qu’il soit utilisable entièrement au clavier

> Reprendre un mega-menu déjà en production sans tout reconstruire : voici comment nous l'avons rendu utilisable au clavier, colonne par colonne, sans casser son apparence.

- Auteur : Clément Hadrot
- Publié le : 2021-04-08
- Mis à jour le : 2021-04-08
- Catégorie : Accessibilité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/accessibilite/mega-menu-existant-utilisable-clavier/

## L’essentiel

- Une flèche vers le bas ouvre le sous-menu, pas un survol seul
- Échap referme et rend le focus à l'en-tête
- Chaque colonne du méga-menu reste accessible en Tab

Le brief de reprise était clair : un site e-commerce de matériel de bricolage, un mega-menu à quatre colonnes déjà en production depuis deux ans, et une seule consigne du client — ne rien casser visuellement, le menu doit rester identique au pixel près. La contrainte usuelle du « je refais tout proprement » n'était pas sur la table : il fallait adapter l'existant, colonne par colonne, sans toucher au CSS de mise en page.

Le mega-menu original ne s'ouvrait qu'au survol de la souris, via un simple `:hover` en CSS, complété d'un peu de JavaScript pour gérer les appareils tactiles. Au clavier, appuyer sur Tab passait directement du premier lien du menu principal au second, sans jamais ouvrir les sous-menus : leur contenu, bien réel dans le DOM, restait invisible et inatteignable pour un utilisateur au clavier seul.

## Étape 1 : cartographier la structure existante

Le HTML du mega-menu, une fois inspecté, suivait une structure raisonnable — une liste de `<li>` de premier niveau, chacun contenant un lien puis un `<div>` de sous-menu masqué par défaut. La logique d'ouverture, elle, était entièrement pilotée par CSS `:hover`, sans le moindre attribut ARIA ni gestion de touche.

```
<li class="menu-item-a-mega">
  <a href="/outillage/">Outillage</a>
  <div class="sous-menu">
    <!-- quatre colonnes de liens -->
  </div>
</li>
```

## Étape 2 : ajouter l'état ouvert/fermé sans toucher au CSS de mise en page

> L'essentiel à retenir : Une flèche vers le bas ouvre le sous-menu, pas un survol seul ; Échap referme et rend le focus à l'en-tête ; Chaque colonne du méga-menu reste accessible en Tab

Plutôt que de réécrire les règles `:hover` déjà validées visuellement, nous avons ajouté une classe d'état pilotée par JavaScript, avec les attributs ARIA nécessaires sur le lien déclencheur :

```
<a href="/outillage/" aria-expanded="false" aria-haspopup="true">Outillage</a>
```

```
document.querySelectorAll('.menu-item-a-mega > a').forEach((lien) => {
  lien.addEventListener('keydown', (event) => {
    if (event.key === 'ArrowDown') {
      event.preventDefault();
      ouvrirSousMenu(lien);
      lien.parentElement.querySelector('.sous-menu a').focus();
    }
    if (event.key === 'Escape') {
      fermerSousMenu(lien);
      lien.focus();
    }
  });
});

function ouvrirSousMenu(lien) {
  lien.setAttribute('aria-expanded', 'true');
  lien.parentElement.classList.add('sous-menu-ouvert');
}
function fermerSousMenu(lien) {
  lien.setAttribute('aria-expanded', 'false');
  lien.parentElement.classList.remove('sous-menu-ouvert');
}
```

La classe `sous-menu-ouvert` reproduit en JavaScript exactement ce que faisait `:hover` visuellement, ce qui a permis de ne modifier aucune règle de mise en page existante : seule la condition de déclenchement change.

## Étape 3 : parcourir les quatre colonnes au Tab, puis en sortir

Une fois le sous-menu ouvert, l'utilisateur doit pouvoir tabuler à travers l'ensemble des liens des quatre colonnes, dans un ordre de lecture cohérent (colonne par colonne, de haut en bas), puis sortir naturellement du sous-menu en continuant à appuyer sur Tab une fois le dernier lien atteint — sans piège de focus, puisqu'un mega-menu n'est pas une fenêtre modale.

## Étape 4 : fermer proprement quand le focus quitte le menu

Un dernier ajustement a été nécessaire : quand l'utilisateur quitte le sous-menu par Tab vers l'élément suivant de la page (et non vers Échap), le sous-menu doit se refermer visuellement, sinon il reste ouvert à l'écran alors que le focus n'y est plus. Un écouteur sur l'événement `focusout`, avec une vérification que le nouveau focus ne se trouve plus dans le sous-menu, referme ce dernier proprement.

## Ce que la reprise nous a coûté, et ce qu'elle a évité

- Environ une journée de développement pour les quatre colonnes, contre plusieurs jours estimés pour une reconstruction complète du mega-menu.
- Aucune régression visuelle signalée en recette, puisque le CSS de mise en page n'a pas été touché.
- Une dette technique documentée : la structure HTML reste perfectible, mais elle est désormais utilisable, ce qui était la priorité du client à ce stade du projet.

## En résumé

Reprendre un mega-menu existant plutôt que le reconstruire est souvent possible en ajoutant une couche d'état ARIA et de gestion de touche par-dessus une logique `:hover` déjà en place, à condition de bien cartographier la structure avant de toucher au moindre script. Le résultat n'est pas toujours l'architecture la plus élégante, mais il répond à la contrainte réelle du projet : rendre utilisable sans tout casser.
