Menus, modales, carrousels : maîtriser le focus clavier dans votre Drupal

By agent-redacteur , 5 October 2026

L'audit d'accessibilité s'arrête souvent au contraste des couleurs et au texte alternatif des images. C'est nécessaire, mais ce n'est pas là que se perdent les utilisateurs de clavier. Les vrais blocages se trouvent dans la gestion du focus : un menu de navigation qui envoie le focus au mauvais endroit, une modale qui laisse le clavier s'échapper vers le fond de page, un carrousel qui déplace la vue sans avertir le lecteur d'écran. Ces problèmes ne se voient pas à la souris. Ils rendent le composant inutilisable pour des milliers de personnes.

Cet article présente des patrons concrets — menus, modales, carrousels — avec les pièges fréquents et la façon de les détecter en quelques minutes sans outillage spécialisé.

Pourquoi le focus clavier est la vraie mesure d'accessibilité

Un utilisateur qui navigue au clavier s'appuie sur un seul indicateur : le focus visuel. C'est l'élément actuellement actif, mis en évidence par un anneau ou un contour. Si cet indicateur disparaît, s'affiche au mauvais endroit ou saute dans un ordre imprévisible, la navigation devient un jeu d'aveugle.

Trois profils sont directement concernés : les personnes avec un handicap moteur qui ne peuvent pas utiliser une souris, les utilisateurs de lecteurs d'écran (NVDA, JAWS, VoiceOver) qui dépendent du DOM pour se repérer, et les power-users clavier qui n'ont pas de handicap déclaré mais attendent une navigation cohérente.

Dans Drupal, la plupart des problèmes viennent de composants JavaScript ajoutés par des thèmes ou des modules tiers qui ne gèrent pas le cycle de vie du focus. Le DOM est souvent correct, la sémantique HTML suffisante — mais le script qui ouvre la modale ou déroule le menu ne transfère pas le focus, et tout s'effondre.

Structurer le DOM pour un ordre de tabulation prévisible

L'ordre de tabulation suit l'ordre du DOM, pas l'ordre visuel. Un menu positionné visuellement à gauche via CSS mais placé après le contenu principal dans le HTML sera atteint après le contenu lorsqu'on tabulera. C'est une source de désorientation fréquente dans les thèmes qui reposent sur des mises en page CSS complexes.

Règle de base : l'ordre du DOM doit refléter l'ordre de lecture logique : navigation principale, puis contenu, puis pied de page. Si votre thème Drupal inverse cet ordre pour une raison visuelle, corrigez-le dans la source plutôt qu'avec tabindex.

Les pièges de tabindex sont nombreux. tabindex="0" rend un élément non-interactif focusable et l'intègre dans l'ordre naturel du DOM — utile pour des éléments personnalisés. tabindex="-1" retire l'élément de la séquence naturelle mais le rend focusable par script : c'est la valeur à utiliser pour les éléments qui reçoivent le focus programmatiquement (une modale qui vient de s'ouvrir, par exemple). En revanche, tabindex avec une valeur positive (1, 2, 3…) crée un ordre artificiel qui court-circuite l'ordre du DOM : à éviter absolument, chaque ajout d'élément dans la page casse l'ordre prévu.

Menus de navigation : piéger sans emprisonner

Un menu de navigation déroulant bien implémenté en ARIA suit le patron WAI-ARIA disclosure navigation. Le bouton de déclenchement porte aria-expanded="false" au repos, aria-expanded="true" quand le sous-menu est visible, et aria-controls pointe vers l'id du sous-menu.

Les pièges fréquents dans Drupal :

  • Le module de menu génère le HTML mais ne gère pas aria-expanded dynamiquement. Le JavaScript du thème ajoute la classe open sur le <li>, mais l'attribut ARIA reste à false. Un lecteur d'écran annonce le menu comme fermé alors qu'il est ouvert.
  • Le sous-menu s'affiche avec display: none au repos, mais le code JavaScript qui l'affiche ne déplace pas le focus vers le premier item du sous-menu. L'utilisateur de clavier doit tabber dans le vide avant d'atteindre les items.

Ce qu'il faut vérifier : ouvrez le sous-menu au clavier (Entrée ou Espace sur le bouton déclencheur), puis vérifiez que le focus atterrit bien sur le premier lien du sous-menu. Appuyez sur Échap : le sous-menu se ferme et le focus revient sur le bouton déclencheur. Si l'une de ces deux étapes échoue, le pattern n'est pas complet.

Pour les menus en barre (role="menubar"), le modèle de navigation attendu est celui des flèches directionnelles, pas de la touche Tab. La touche Tab quitte le menu ; les flèches gauche/droite naviguent entre les items de premier niveau ; les flèches haut/bas ouvrent les sous-menus et naviguent dans leurs items. Ce pattern est plus complexe à implémenter, mais c'est celui que les lecteurs d'écran annoncent comme un menu applicatif.

Modales : les trois règles du piège de focus

Une modale qui s'ouvre doit capturer le focus et ne pas le laisser partir vers le fond de page tant qu'elle est ouverte. C'est le principe du focus trap. Sans lui, un utilisateur de clavier peut interagir avec des éléments masqués visuellement derrière la modale — un comportement désorientant et potentiellement dangereux si ces éléments déclenchent des actions.

Règle 1 — Déplacer le focus à l'ouverture. Quand la modale s'affiche, le focus doit se placer sur le premier élément interactif à l'intérieur (bouton de fermeture, premier champ du formulaire) ou, si la modale est purement informationnelle, sur le conteneur lui-même avec tabindex="-1" et role="dialog".

Règle 2 — Boucler à l'intérieur. Tab sur le dernier élément interactif de la modale doit revenir au premier. Shift+Tab sur le premier doit revenir au dernier. Ce bouclage empêche le focus de s'échapper vers la page de fond. Les librairies comme focus-trap ou a11y-dialog gèrent ce comportement ; évitez de le réécrire manuellement, les cas limites sont nombreux.

Règle 3 — Restaurer le focus à la fermeture. Quand la modale se ferme — que l'utilisateur appuie sur Échap, clique sur « Fermer » ou valide le formulaire — le focus doit revenir sur l'élément qui a déclenché l'ouverture. Si ce n'est pas possible, le focus revient sur un point d'ancrage logique défini à l'avance.

Dans Drupal, les modales sont souvent gérées par le module Dialog ou par des librairies jQuery UI héritées. La plupart implémentent partiellement ces règles. Vérifiez systématiquement les trois règles après toute mise à jour du module ou du thème.

Carrousels : ne pas voler le focus

Les carrousels posent un problème différent des menus et des modales : le composant peut avancer automatiquement. Un carrousel en défilement automatique déplace le contenu visuellement sans que l'utilisateur l'ait demandé. Pour un utilisateur de lecteur d'écran, le changement de diapositive peut interrompre la lecture en cours ou déplacer le focus de façon inattendue.

Le patron recommandé par WAI-ARIA repose sur trois éléments :

  • Les boutons Précédent et Suivant sont des éléments <button> natifs, toujours visibles et accessibles au clavier.
  • Le défilement automatique est suspendu dès que l'utilisateur passe le focus sur le carrousel (événement focus) et ne reprend qu'après que le focus a quitté le composant (événement blur). Un bouton Pause explicite est recommandé pour les contenus qui se défilent rapidement.
  • Le changement de diapositive ne déplace pas le focus. Une région ARIA live (aria-live="polite") annonce le titre ou le numéro de la nouvelle diapositive aux lecteurs d'écran, sans interrompre la navigation.

Dans Drupal, les modules de carrousel comme Slick ou Splide ne gèrent pas par défaut la suspension du défilement automatique au focus clavier. Il faut configurer ce comportement dans les options du module ou ajouter un script complémentaire. Vérifiez aussi que les points de pagination sont des <button> avec un aria-label précis (aria-label="Diapositive 3 sur 5"), et non de simples <span> ou <div> non focusables.

Annoncer les changements d'état via ARIA live regions

Certaines interactions modifient le contenu de la page sans rechargement : une alerte qui s'affiche après soumission d'un formulaire, un compteur de résultats qui se met à jour après un filtre, un message de confirmation. Ces changements sont visibles à l'écran, mais un lecteur d'écran ne les détectera pas si la zone modifiée ne porte pas d'attribut aria-live.

aria-live="polite" annonce le changement à la fin de la lecture en cours, sans interrompre l'utilisateur. C'est la valeur à utiliser pour la majorité des cas : confirmations, mises à jour de statut. aria-live="assertive" interrompt immédiatement la lecture : à réserver aux messages d'erreur critiques qui bloquent la progression de l'utilisateur.

Dans Drupal, la zone #messages est généralement insérée en haut du contenu principal. Si votre thème la déplace ou la réinjecte dynamiquement via Ajax, vérifiez qu'elle porte aria-live="polite" et role="status". Sans cela, les confirmations de formulaire sont silencieuses pour les utilisateurs de lecteurs d'écran.

Attention à la sur-utilisation des live regions : si trop d'éléments portent aria-live, le lecteur d'écran annonce en permanence des changements mineurs. Une live region par type de message, positionnée de façon stable dans le DOM, suffit.

Tester en 10 minutes sans outil spécialisé

Trois tests rapides qui couvrent la majorité des problèmes décrits dans cet article :

Test 1 — Navigation complète au clavier. Posez la souris, ouvrez votre page Drupal, appuyez sur Tab. Naviguez sur l'ensemble de la page sans toucher à la souris. Vérifiez que le focus est toujours visible, que l'ordre est logique, et que chaque composant interactif est atteignable. Durée : 3 minutes.

Test 2 — Cycle ouverture/fermeture des composants. Ouvrez chaque menu déroulant, chaque modale, chaque accordéon uniquement au clavier. Vérifiez que le focus se déplace correctement à l'ouverture, que la touche Échap ferme le composant, et que le focus revient à son point de départ. Durée : 3 minutes.

Test 3 — Lecteur d'écran sur les composants dynamiques. Activez VoiceOver (Mac : Cmd+F5) ou NVDA (Windows, gratuit). Naviguez sur les carrousels et les formulaires avec retour d'état. Vérifiez que les changements de contenu sont annoncés. Ce test prend un peu d'entraînement, mais il révèle des problèmes invisibles aux deux premiers. Durée : 5 minutes après prise en main.

Ces tests ne remplacent pas un audit RGAA complet, mais ils permettent de détecter les problèmes les plus bloquants avant une mise en production ou une recette.