Les liens d'évitement
Le lien d'évitement est le premier élément focalisable de la page, invisible jusqu'à ce qu'on le tabule. Il ne vaut que si sa cible peut recevoir le focus. Démo, code, critères RGAA.
4 critères RGAA en jeu
Essayez-les
Le rapport d’audit
Un titre ne reçoit pas le focus. Un lien qui le vise fait défiler la page jusqu’à lui et s’arrête là.
Un lien, pour voir où mène la tabulation suivanteActivez l’un des deux liens d’évitement pour voir où le focus atterrit.
Posez le focus dans la page miniature et tabulez : deux liens d’évitement apparaissent avant le menu. Activez le premier, puis appuyez sur
Tab — le rapport indique la zone de contenu, puis le lien qui s'y trouve. Remontez en Maj + Tab et recommencez avec le second : la page défile au même endroit et le Tab suivant mène au même lien, mais le rapport indique cette fois **le corps du document** — rien ne porte le focus. Seule leur cible diffère, et le rapport dit laquelle l'a reçu.Cette démo existe aussi en page autonome.
L’erreur courante
Le lien d’évitement écrit une fois, jamais essayé au clavier.
<!-- À ne pas faire -->
<a class="evitement" href="#contenu">Aller au contenu</a>
…
<main id="contenu">…</main> /* À ne pas faire : ce qui n'est pas affiché ne prend pas le focus */
.evitement {
display: none;
}
.evitement:focus {
display: block;
} Deux fautes, et la seconde est celle que personne ne voit.
display: none retire l’élément de l’ordre de tabulation. Le :focus qui
suit ne se déclenchera donc jamais : pour qu’il s’applique, il faudrait que le
lien puisse recevoir le focus, ce que la règle précédente lui interdit. Le lien
est dans le code, il n’existe pour personne. visibility: hidden et l’attribut hidden produisent exactement le même résultat.
Mais même corrigé, ce lien reste à moitié cassé, parce que <main> ne peut
pas recevoir le focus. Le navigateur fait défiler la page et pose sur la cible
le point de départ de la tabulation : le Tab suivant continue bien
dans le contenu. Mais aucun élément ne porte le focus — document.activeElement retombe sur body. Rien n’est annoncé, aucun indicateur de focus n’est
visible, et le point de départ se perd dès qu’un script re-rend la zone ou
déplace le focus. Le glossaire exige de reprendre « la lecture et la
navigation clavier » : sans tabindex="-1", seule la seconde moitié est
acquise.
Trois variantes de la même méprise :
- La cible est un titre :
href="#titre-page"vers un<h1 id="titre-page">. Un titre n’est pas focalisable ; c’est le cas le plus fréquent, parce qu’il paraît le plus naturel. tabindex="0"sur la cible au lieu de-1: le contenu principal devient un arrêt de tabulation pour tout le monde, sur toutes les pages, sans que personne n’ait rien demandé.- Le lien réutilise la classe
sr-only, ou se réduit àwidth: 0; height: 0, sans neutralisation au focus : il est bien focalisable — un élément de dimension nulle reste dans l’ordre de tabulation —, mais reste invisible une fois atteint. À la souris, personne ne le remarque ; au clavier, le focus disparaît de l’écran.
Le code, pas à pas
1. Un lien, en tête du code source
<!-- Le tout premier élément du corps de la page -->
<a class="evitement" href="#contenu">Aller au contenu</a>
<header>…</header>
<nav>…</nav>
<main id="contenu" tabindex="-1">…</main> C’est un <a href>, pas un bouton : il mène à un endroit de la page, et le
navigateur sait déjà tout faire. Sa place est avant ce qu’il permet
d’éviter — placé après le menu, il ne fait plus rien gagner.
Le test 12.7.2 ajoute une exigence d’ensemble : dans chaque ensemble de pages — une rubrique, un blog, un espace client —, ce lien doit être au même endroit dans la présentation et dans le même ordre relatif dans le code. Il appartient au gabarit, pas à la page.
2. Le masquer sans le rendre inatteignable
.evitement {
position: absolute;
top: 0.5rem;
left: 0.5rem;
transform: translateY(-200%);
}
.evitement:focus {
transform: translateY(0);
} Le lien reste affiché et focalisable ; il est simplement déplacé hors du champ
visible. La technique importe peu — transform, top: -100%, la classe sr-only complétée d’un :focus — pourvu qu’elle ne repose ni sur display: none, ni sur visibility: hidden, ni sur l’attribut hidden.
Le référentiel admet aussi un lien toujours visible : le test 12.7.2 demande qu’il soit « visible ou, à défaut, visible à la prise de focus ». Le masquer est une convention d’usage, pas une obligation. Un lien d’évitement permanent est plus simple à écrire, et plus difficile à casser.
Ne supprimez pas l’outline en stylant ce lien. Il apparaît au moment même où il prend le focus : c’est le seul repère qui dise où l’on se trouve.
3. tabindex="-1" sur la cible — le point qu’on rate
<main id="contenu" tabindex="-1">…</main> Une ancre déplace le défilement. Elle ne déplace le focus que si l’élément visé
peut le recevoir — et <main>, <div>, <section>, <h1> ne le peuvent pas.
tabindex="-1" rend l’élément focalisable par script et par ancre, sans
l’ajouter à l’ordre de tabulation. C’est la valeur exacte dont on a besoin ici : 0 l’ajouterait à l’ordre de tabulation, ce qu’on ne veut pas.
Le glossaire du référentiel est explicite sur ce qu’est un lien fonctionnel :
Un lien d’évitement ou d’accès rapide fonctionnel est un lien dont l’activation permet de reprendre la lecture et la navigation clavier à partir de la cible du lien lors de l’utilisation des navigateurs et des aides techniques retenus dans l’environnement de test […] de l’audit.
La vérification ne consiste pas à regarder où mène le Tab suivant : il continue dans le contenu dans les deux cas. Elle consiste à demander si quelque chose porte le focus après l’activation. Tab,
Entrée, puis un coup d'œil : la cible porte-t-elle un indicateur de focus ? Dans la console, `document.activeElement` désigne-t-il la cible, ou `body` ? Si c'est `body`, la cible ne prend pas le focus.4. Plusieurs liens, quand la page les justifie
Un seul lien est exigé, vers la zone de contenu principal. Le critère 12.6 permet d’en ajouter d’autres — vers la recherche, vers la navigation — comme l’un des moyens de rendre ces zones atteignables ou évitables.
Ce n’est pas la seule façon de satisfaire 12.6 : un rôle de landmark correspondant à la nature de la zone suffit. Cinq liens d’évitement en tête de page coûtent cinq tabulations à qui n’en voulait qu’une ; deux ou trois au maximum — c’est un usage, pas une exigence du référentiel — et des landmarks pour le reste.
5. Dans une application à navigation par script
Un routeur qui intercepte le clic et rend la vue lui-même ne fait pas ce que fait le navigateur. Après un changement de page, le focus reste où il était, souvent sur le corps du document : le lien d’évitement en devient inopérant, et rien ne le signale.
La correction est la même partout : appeler cible.focus() explicitement après
le rendu, sur un élément qui porte tabindex="-1".
6. Les landmarks ne dispensent pas du lien
<main>, <nav>, <header> permettent à un lecteur d’écran de sauter d’une
zone à l’autre, et c’est précieux. Mais le critère 12.7 exige un lien, et pour
une raison qui n’a rien de formel : une personne qui navigue au clavier sans lecteur d’écran n’a aucun accès aux landmarks. Pour elle, le menu se retabule
en entier à chaque page tant que le lien n’existe pas.
Au clavier
| Touche | Effet |
|---|---|
| Tab (au chargement) | Amène le focus sur le lien d’évitement, qui devient visible. Il est le premier élément focalisable de la page. |
| Entrée | Active le lien : la page défile jusqu’à la cible et le focus s’y déplace, si elle porte tabindex="-1". Sans lui, la page défile seule et document.activeElement retombe sur body. |
| Tab (après activation) | Va au premier élément focalisable du contenu — dans les deux cas : le navigateur a posé là le point de départ de la tabulation. Cette touche ne dit donc pas si le focus a suivi ; l’indicateur de focus sur la cible, si. |
| Maj + Tab | Revient sur le lien d’évitement, qui réapparaît. |
Ce que le lecteur d’écran restitue
Sur le lien : son intitulé et sa nature — « Aller au contenu, lien ». Après
activation, c’est la cible qui est annoncée : sur un <main> porteur de tabindex="-1", de l’ordre de « Contenu principal, région principale », puis
le début du contenu. La formulation varie d’un lecteur à l’autre ; les
informations, non.
Si après activation vous n’entendez rien — ni la région, ni le début du
contenu —, c’est que rien n’a reçu le focus : document.activeElement est
retombé sur body, la cible n’est pas focalisable. Le silence est le
symptôme, pas une nouvelle annonce du lien. Si vous n’entendez jamais le lien en
tabulant depuis le haut de la page, il est masqué par display: none — ou bien
quelque chose le précède dans l’ordre de tabulation.
Checklist
- Un
<a href="#…">, premier élément focalisable de la page. - Masqué par un déplacement hors champ, jamais par
display: nonenihidden. - Visible à la prise de focus, avec son indicateur de focus intact.
- La cible porte
tabindex="-1"—-1, pas0. - Vérifier après activation que la cible porte bien le focus, et pas
body. - Même place et même ordre relatif dans tout l’ensemble de pages.
- Bonne pratique : deux ou trois liens au maximum, des landmarks pour les autres zones (le RGAA n’en fixe pas de plafond).
Les critères RGAA en jeu
- Critère 12.7 — Lien d’évitement vers le contenu
Le test 12.7.2 exige un lien fonctionnel et visible au moins à la prise de focus : caché en display none il ne prend jamais le focus, et pointé sur une cible qui ne le reçoit pas il déplace la vue sans poser le focus — rien n'est annoncé, rien ne montre où l'on est.
- Critère 12.6 — Zones de regroupement atteignables
Le lien d'évitement est l'un des cinq moyens admis pour qu'une zone soit atteinte ou évitée : c'est par lui que l'en-tête et le menu cessent de se retabuler en entier à chaque page.
- Critère 12.8 — Cohérence de l’ordre de tabulation
Sans focus posé sur la cible, la suite de la tabulation ne tient qu'au point de départ que le navigateur pose seul : le moindre script qui déplace le focus ailleurs le perd, et la tabulation repart du menu qu'on venait d'éviter.
- Critère 10.7 — Visibilité de la prise de focus
Le lien n'existe à l'écran qu'au moment où il prend le focus. Le styler en supprimant l'outline le rend invisible précisément quand il doit se voir.
Vérifiez votre composant avec l'extension
Pour aller plus loin
- Critère 12.7 — Lien d’évitement vers le contenu : la méthode de vérification en quatre étapes, et ce que notre moteur sait en dire.
- Critère 12.6 — Zones de regroupement atteignables : les cinq moyens admis, dont le lien d’évitement n’est que le quatrième.
- « Liens d’évitement ou d’accès rapide » au glossaire : la définition qui fixe ce qu’est un lien fonctionnel.
- « Zone de contenu principal » au glossaire : ce que la cible doit contenir, et ce qu’elle doit exclure.
- Les liens : ce que chaque lien doit annoncer, sorti de sa phrase.
Sources
- MDN — l’attribut
tabindex— pourquoi-1rend focalisable sans tabuler - HTML — sequential focus navigation starting point — pourquoi le Tab continue dans le contenu sans que rien n’ait le focus
- WCAG — Understanding 2.4.1 Bypass Blocks — l’exigence dont 12.7 découle
- W3C WAI Tutorials — Page Structure — les zones de page, et comment les baliser
- GOV.UK Design System — Skip link — une implémentation de référence, cible comprise