Toute belle histoire commence par…
Il était une fois
Il y a bien longtemps (pas tant que ça mais bon), à chaque fois que vous cliquiez sur un bouton, vous pouviez entendre un ou une PO/utilisateur/designer/dev/autre dire :
- « Oh, cette vilaine bordure bleue ou noire est-ce qu’on pourrait l’enlever ? »
- Mais c’est nécessaire pour les utilisateurs de clavier !
- Oui mais c’est moche, on peut l’enlever ? À propos, je n’utilise pas mon clavier.
- (ton qui monte) C’est nécessaire pour les utilisateurs de clavier !!!
- Oui mais c’est laid, on peut l’enlever ? À propos, je n’utilise pas mon clavier.
- Etc.
La cause principale de ces discussions interminables était la suivante : cliquer sur un élément active les styles de focus, comme avec le clavier.
Il était impossible de différencier un bouton activé via une souris ou un clavier (les deux avaient des styles de focus déclenchés), sauf avec des tonnes de JavaScript à coup sûr. En général, cela se finissait par un drame, un bon gros outline: 0
des familles, soit la suppression complète et entière de l’indicateur visuel pour le clavier. Nigro notanda lapillo.
C’est là que :focus-visible
, anciennement appelé :focus-ring
(l’idée n’est vraiment pas récente), entre en jeu pour sauver nos âmes.
Le besoin
L’un des besoins les plus élémentaires lors de l’utilisation d’un clavier est de pouvoir savoir où vous vous trouvez dans l’interface.
S’il n’y a pas de surbrillance visible de l’élément actuel, l’utilisateur peut se perdre, la navigation devient vraiment pénible et une opération simple comme atteindre un lien nécessite soudainement une attention folle… ou n’est tout simplement pas possible.
Dans le langage expert de l’accessibilité, si je ne me trompe pas, dans les WCAG, c’est le Success Criterion 2.4.7 Focus Visible: Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible (traduction approximative : toute interface utilisable au clavier a un mode d’utilisation où le focus clavier est visible).
En pratique
Avant, on doublait les styles entre :focus
et :hover
, et on priait pour que ça passe côté produit sans prendre de remarque comme au début de cet article.
Là, on peut se permettre de totalement virer l’outline
au :hover
, et de bien renforcer ce dernier avec :focus-visible
.
Quelque chose comme :
.mon-button:focus {
outline: none;
}
.mon-button:focus-visible {
outline: 3px solid chartreuse;
// je ne peux être tenu responsable du choix de cette couleur.
}
Comment :focus-visible
marche
Même si l’on pourrait croire que c’est de la magie… il n’y a aucune magie là dedans. Grosso modo, le navigateur utilise certaines heuristiques pour déterminer si – selon lui – l’utilisation doit déclencher :focus-visible
ou non.
TLDR : si l’utilisateur utilise le clavier.
En réalité, c’est un peu plus complexe : je vous conseille de lire la spécification de :focus-visible
.
Je ne vais pas tout détailler, d’autres l’ont bien fait comme How do browsers determine when something is :focus-visible?, mais je m’arrête sur un exemple, les formulaires.
On pourrait se dire assez légitimement « si je clique sur un champ de formulaire, :focus-visible
ne sera pas activé ». Sauf que non ! Si un élément – comme un champ de formulaire – a besoin du clavier pour fonctionner, il activera :focus-visible
, qu’on clique dessus ou qu’on l’atteigne au clavier.
En pratique, cela se gère très facilement.
C’est pour cela que je vous invite à lire la spécification et à tester. D’expérience, j’ai vu quelques cas qui ont du sens une fois la spécification lue, mais qui peuvent surprendre (si une modale apparait subitement au lancement du site avant que l’utilisateur n’ait pu interagir, etc.).
La compatibilité
Le support est excellent sur les navigateurs récents : :focus-visible
sur Can I Use. Le souci est comme d’habitude IE11 (mais on s’en fout) et quelques vieux Safari, à vous de voir si vous vous en foutez ou non.
Là où c’est gênant avec ces Safari, c’est que comme ils ne reconnaissent pas du tout :focus-visible
, ils décident de purement ignorer la ligne… et parfois d’autres lignes factorisées avec. Ce qui amène à des commentaires amusants.
Au pire, vous avez un outil magique pour déployer en douceur : @supports selector(:focus-visible) {
. En clair, si :focus-visible
est supporté, alors… faire quelque chose.
Il a pu m’arriver de le déployer en douce, et – constatant que personne n’avait rien trouvé à redire en 6 mois – d'annoncer fièrement que c’était en production depuis une demi-année sans que personne ne s’en soit jamais plaint.
Pour conclure
Cette pseudo-classe est un régal à utiliser, et elle permet enfin de concilier demandes de designs et accessibilité, voir de même séparer totalement l’expérience clavier du reste. Albo notanda lapillo.