Parcours de l’ordre de tabulation

Appuyez sur Tab sur une page web et le focus saute au lien, bouton ou champ suivant. Cette vérification écrit tout le trajet pour n’importe quelle adresse et désigne les contrôles qui en ont été laissés de côté.

Un seul passage sur la page et au plus cinq de ses propres feuilles de style. Rien n’est conservé.

Ou essayez mozilla.org, wikipedia.org

Le focus est le curseur du clavier

Une souris peut pointer n’importe où. Un clavier ne peut être « sur » qu’un seul élément à la fois et cette position s’appelle le focus. Tab l’avance, Maj+Tab le recule, Entrée suit un lien, Espace appuie sur un bouton. Les personnes qui ont des tremblements ou une motricité limitée se déplacent ainsi. Les utilisateurs de lecteurs d’écran aussi, ceux qui emploient des commutateurs ou la commande vocale et quiconque remplit vite des formulaires.

Le navigateur détermine ce qui peut recevoir le focus à partir du seul HTML. Les liens avec un href, les boutons, les champs de formulaire, <summary>, les lecteurs multimédias avec commandes et les cadres sont sur le trajet par défaut, dans l’ordre où ils apparaissent dans le code source. Tout le reste est sauté, sauf si un attribut tabindex dit le contraire.

Les trois sens de tabindex

ValeurEffetQuand l’utiliser
tabindex="0"Ajoute l’élément au trajet à sa position naturelleContrôles personnalisés qui ne peuvent pas être un <button> natif
tabindex="-1"Le retire du trajet ; les scripts peuvent toujours lui donner le focusOnglets inactifs, éléments de menu atteints avec les flèches, diapositives de carrousel hors écran
tabindex="1" ou plusLe place devant tout le reste, le plus petit nombre d’abordPresque jamais. Le focus saute dans tous les sens à l’écran

Le parcours suit ces règles à la lettre : valeurs positives d’abord en ordre croissant, puis ordre du code source. Un groupe de boutons radio de même name compte pour un seul arrêt, puisque les flèches se déplacent à l’intérieur du groupe. Les contrôles désactivés, les éléments <dialog> fermés, les zones inert ou hidden et le contenu des <details> fermés sont écartés.

Ce que la vérification signale

Éléments cliquables que le clavier ne peut pas atteindre
Un <div onclick> ou un élément avec role="button" et sans tabindex. Les utilisateurs de souris peuvent appuyer dessus et les utilisateurs du clavier ne peuvent même pas y arriver. Remplacez-le par <button type="button">, qui apporte gratuitement le focus, Entrée et Espace.
Liens sans href
Pour le navigateur, un <a> sans destination est du texte ordinaire et Tab passe tout droit.
Contrôles avec tabindex="-1"
Signalés, sauf si le lien double un autre lien accessible vers la même adresse, ou appartient à une liste d’onglets, un menu, une barre d’outils ou un groupe semblable où les flèches prennent le relais.
Lien d’évitement
La vérification cherche dans les trois premiers arrêts un lien vers une ancre de la même page, comme <a href="#content">Aller au contenu</a> et confirme que l’id cible existe. Elle compte aussi combien d’appuis il faut pour aller du haut de la page à <main>. Avec cinq ou moins, un lien d’évitement absent est seulement noté à titre d’information.
Contour de focus
Nous cherchons dans les blocs <style> de la page, les styles en ligne et jusqu’à cinq feuilles de style du même site des règles comme a:focus { outline: none } ou * { outline: 0 }. Si rien ne remplace le contour par des styles :focus-visible ou :focus, le constat est rouge, car les utilisateurs du clavier ne peuvent pas voir où ils sont.
Autres arrêts qui méritent un coup d’œil
Les éléments focalisables dans aria-hidden="true", les arrêts sans nom accessible, les cadres sans title et les liens vers # ou javascript: qui jouent le rôle de boutons.

Rétablir un focus visible

Les designers suppriment souvent le contour parce qu’il apparaît après un clic de souris et qu’ils le trouvent laid. Le sélecteur :focus-visible règle la dispute. Il ne correspond que quand le navigateur juge que l’utilisateur a besoin de voir le focus, ce qui veut dire en pratique l’usage du clavier.

:focus-visible {
  outline: 3px solid #1a5fb4;
  outline-offset: 2px;
}

WCAG 2.2 demande un indicateur avec un contraste d’au moins 3:1 par rapport aux couleurs environnantes. Le motif :focus:not(:focus-visible) { outline: none } est sûr et n’est pas signalé.

Limites d’une lecture statique

Le trajet est calculé à partir du HTML que reçoit notre serveur. Les gestionnaires de clic attachés en JavaScript avec addEventListener ne laissent aucune trace dans le code : un <div> câblé ainsi passe donc inaperçu. Les menus construits par script sont aussi invisibles ici, comme les pièges au clavier, où le focus entre dans un widget et n’en peut plus sortir. Les feuilles de style d’un autre domaine, ou au-delà de la cinquième, ne sont pas lues.

Terminez par le vrai test, qui prend deux minutes. Mettez la souris de côté, chargez la page et appuyez sur Tab jusqu’au pied de page. Vous devez toujours voir où vous êtes et pouvoir ouvrir chaque menu et envoyer chaque formulaire.

Questions fréquentes

Comment tester moi-même la navigation au clavier ?

Cliquez dans la barre d’adresse, puis appuyez sur Tab encore et encore. Maj+Tab revient en arrière, Entrée agit sur les liens, Espace sur les boutons et les cases à cocher, les flèches dans les groupes de boutons radio et les menus et Échap ferme les boîtes de dialogue. Sur Safari macOS, activez d’abord « Appuyer sur Tab pour surligner chaque élément d’une page web » dans les réglages avancés.

Un tabindex="0" sur un div suffit-il à en faire un bouton ?

Non. Il rend l’élément focalisable, mais Entrée et Espace ne font rien tant que vous n’ajoutez pas de gestionnaires de touches et un lecteur d’écran ne l’appellera pas bouton sans role="button". Un <button> natif vous donne les trois.

Ai-je besoin d’un lien d’évitement si ma page a un élément main ?

Oui, pour les utilisateurs voyants du clavier. Les lecteurs d’écran peuvent sauter au repère <main> par un raccourci. Quelqu’un qui n’utilise que la touche Tab n’a pas de tel raccourci et doit parcourir chaque élément du menu, sauf si vous offrez un lien d’évitement.

Pourquoi l’ordre de tabulation ne correspond-il pas à ce que je vois à l’écran ?

Tab suit l’ordre du code source HTML, pas la mise en page visuelle. Du CSS comme order, flex-direction: row-reverse, le placement en grille ou le positionnement absolu peut déplacer des éléments à l’écran sans changer leur place dans le code. Un tabindex positif a le même effet.

outline: none est-il toujours un défaut d’accessibilité ?

Seulement quand rien ne le remplace. Une règle qui supprime le contour et définit une bordure, un fond ou une ombre visibles au focus dans le même bloc est correcte et cette vérification la compte comme un remplacement.