Des indicateurs de focus qui se voient vraiment
Voici une manière classique de se tromper : en pleine refonte, quelqu’un
remarque que le contour de focus par défaut du navigateur jure avec les
nouveaux boutons et ajoute outline: none à la feuille de réinitialisation.
Le contrôle visuel passe, parce que rien ne change à l’œil — jusqu’à ce
qu’arrive le premier signalement d’une personne qui navigue au clavier,
parcourant avec Tab une page qui ne montre plus où elle se trouve.
Un indicateur de focus est le repère visible qui montre sur quel élément la
saisie au clavier va agir, et le supprimer rend une interface inutilisable
sans souris. La WCAG 2.4.7 exige un indicateur de focus visible au niveau AA,
et cet indicateur a besoin d’un contraste de 3:1 avec les couleurs qui
l’entourent. Le correctif qui marche : ne jamais mettre outline: none sans
le remplacer, styler l’anneau avec :focus-visible, et s’assurer qu’il se
voit sur chaque arrière-plan où il peut atterrir. C’est sur ce dernier point
que la plupart des anneaux échouent en silence, et c’est ce que ce chapitre de
notre guide du contraste décortique avec des chiffres
calculés.
Pourquoi les indicateurs de focus existent-ils ?
Un utilisateur de souris a une réponse permanente à la question « où suis-je ? » : le pointeur est à l’écran, et l’élément situé dessous réagit. Un utilisateur au clavier qui parcourt une page avec Tab n’a qu’un seul équivalent — l’indicateur de focus. Il en va de même pour les personnes qui utilisent des dispositifs de commutation, et pour quiconque dont les mains, les yeux ou la configuration rendent la souris impraticable. L’anneau n’est pas une décoration posée sur la navigation ; il est le retour d’information de la navigation.
C’est la bonne façon de voir outline: none : il ne nettoie pas un détail
visuel, il éteint le pointeur de quelqu’un. L’interface fonctionne encore au
sens où Tab déplace toujours le focus — mais de façon invisible, ce qui, pour
la personne qui appuie sur Tab, revient à ne pas fonctionner.
Qu’exigent les règles WCAG ?
L’exigence centrale est le critère de succès 2.4.7, Focus visible : toute interface utilisable au clavier doit afficher un indicateur de focus visible. Il se situe au niveau AA — le palier que la réglementation cite généralement — donc un anneau manquant est un défaut de conformité, pas un choix de style.
La visibilité est assortie d’un chiffre. Le critère de contraste des éléments non textuels réclame 3:1 pour l’information visuelle nécessaire à l’identification des composants d’interface, et un indicateur de focus est exactement ce genre d’information — le plancher utile est donc de 3:1 entre l’anneau et les couleurs qui le jouxtent.
La WCAG 2.2 a élargi le tableau : Focus non masqué (2.4.11, AA) stipule que l’élément ayant le focus ne peut pas être entièrement caché derrière d’autres contenus — les en-têtes fixes et les bandeaux de cookies sont les coupables habituels — et un critère AAA plus strict décrit plus en détail la taille et le contraste minimum de l’indicateur. Les détails du palier AAA sont facultatifs et plus rarement visés ; les enseignements fiables sont l’anneau visible, le plancher de 3:1, et le fait de ne pas enterrer l’élément focalisé.
Par quoi remplacer outline: none ?
La raison historique pour laquelle les concepteurs supprimaient l’anneau, c’est
que :focus se déclenche aussi au clic de souris, si bien que les boutons
restaient allumés après avoir été cliqués. Ce problème a une solution en forme
de sélecteur : :focus-visible s’applique quand le navigateur juge que le focus
doit être montré — la navigation au clavier, pour l’essentiel — et ignore les
clics de souris ordinaires.
/* laisser les clics de souris discrets, garder l'anneau pour le clavier */
:focus {
outline: none;
}
:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
}
Cela préserve à la fois l’esthétique qui motivait la suppression et la bouée de
sauvetage que la suppression coupait. Une mise en garde : associez les deux
règles comme ci-dessus — outline: none sur :focus seul, sans règle
:focus-visible à côté, recrée le problème d’origine.
Pourquoi une seule couleur d’anneau fonctionne rarement partout ?
Parce que l’anneau est évalué par rapport à ce sur quoi il atterrit, et un vrai
produit compte de nombreux arrière-plans. Voici une couleur d’anneau — un bleu
de marque, #2563eb — testée contre quatre surfaces qu’elle rencontrerait
réellement, chaque ratio étant calculé :
| Surface | Anneau vs surface | Plancher 3:1 |
|---|---|---|
carte blanche #FFFFFF | ≈5,2:1 | passe |
panneau teinté #EFF6FF | ≈4,8:1 | passe |
bouton de marque #2563eb | 1:1 | invisible |
en-tête sombre #111827 | ≈3,4:1 | passe, marge étroite |
L’échec n’est pas aléatoire — il tombe sur le bouton aux couleurs de la marque, souvent l’élément le plus focalisé de la page, et il est total : un anneau de la même couleur que son arrière-plan n’échoue pas progressivement, il disparaît. L’en-tête sombre passe de justesse. Une couleur, quatre verdicts.
C’est pourquoi une couleur de focus gagne à être traitée comme une décision par surface plutôt que comme une constante globale. Ouvrez le panneau des rôles de focus dans Scale Composer — il dérive un rôle de focus pour chaque surface de la palette et le vérifie contre cette surface au moment de la dérivation, de sorte que l’anneau qui atterrit sur le remplissage de marque n’est pas l’anneau qui atterrit sur la carte blanche.

Comment un anneau bicolore corrige-t-il le problème ?
Si la conception veut un seul style de focus partout, le motif robuste est un
anneau à deux couches — une ligne intérieure claire et une extérieure sombre (ou
l’inverse). Le raisonnement est arithmétique : aucune couleur seule ne contraste
avec tous les arrière-plans, mais une couleur claire et une sombre couvrent
ensemble toute la plage, parce que toute surface est soit assez claire pour la
couche sombre, soit assez sombre pour la couche claire. Les mêmes quatre
surfaces, avec un anneau intérieur blanc et un anneau extérieur #111827
presque noir :
| Surface | intérieur blanc | extérieur #111827 | une couche ≥3:1 ? |
|---|---|---|---|
carte blanche #FFFFFF | 1:1 | ≈17,7:1 | oui |
panneau teinté #EFF6FF | ≈1,1:1 | ≈16,3:1 | oui |
bouton de marque #2563eb | ≈5,2:1 | ≈3,4:1 | oui — les deux |
en-tête sombre #111827 | ≈17,7:1 | 1:1 | oui |
Chaque couche échoue quelque part ; la paire n’échoue nulle part. En CSS, les
deux couches sont typiquement un outline plus une box-shadow, ou deux ombres
empilées.
Le décalage et l’épaisseur comptent-ils ?
Oui, et dans le même sens que le contraste. Un filet de 1px collé au bord de l’élément a tendance à disparaître même quand sa couleur passe techniquement — il se lit comme une partie de la bordure, et le long d’un bord coloré, c’est un seul pixel d’information censé porter tout le signal. Un plancher courant qui marche est un anneau de 2px avec environ 2px de décalage : l’écart sépare l’anneau de l’élément pour qu’il se lise comme un indicateur plutôt qu’une bordure, et l’épaisseur survit au rendu sous-pixel et aux écrans de moindre qualité. Le critère d’apparence AAA de la WCAG 2.2 va dans le même sens, en demandant un indicateur de taille substantielle, pas seulement une couleur conforme.
Donnez à chaque surface son propre anneau
Le tableau à quatre surfaces ci-dessus est réduit ; une vraie palette compte plus de surfaces et un changement de thème les double. Dérivez des rôles de focus sur vos propres surfaces — ajoutez un en-tête sombre ou un panneau teinté et regardez la couleur de focus s’adapter à chaque surface, chaque paire étant vérifiée contre le plancher de 3:1 au fur et à mesure de sa dérivation.