Chapitre 46 : Indicateurs visuels d'accessibilité avec la propriété outline
Personnalisation sécurisée des contours de focus sans compromettre l'accessibilité
L'accessibilité numérique ne se limite pas à l'ajout d'attributs ARIA ou à la structure sémantique du HTML. Elle concerne également la capacité d'un utilisateur, notamment ceux naviguant au clavier ou avec des technologies d'assistance, à savoir précisément où ils se trouvent dans l'interface. C'est ici qu'intervient la propriété outline, souvent mal aimée des designers mais vitale pour l'inclusion.
La propriété outline et le focus
1. Quoi
La propriété outline permet de tracer une ligne autour d'un élément, à l'extérieur de sa bordure (border). Contrairement à la bordure, l'outline ne prend pas de place dans le box-model de l'élément. Cela signifie que l'ajout ou la modification d'un contour n'entraînera jamais de décalage des éléments voisins (pas de "layout shift").
Elle se compose de trois sous-propriétés :
outline-width: L'épaisseur de la ligne.outline-style: Le type de ligne (solid, dashed, dotted, double).outline-color: La couleur de la ligne.
2. Pourquoi
Dans un flux de navigation au clavier (via la touche Tab), l'indicateur de focus est le seul repère visuel de l'utilisateur. Si cet indicateur est supprimé ou rendu invisible, l'interface devient totalement inutilisable pour une personne ne pouvant pas utiliser de souris.
L'utilisation de outline plutôt que border pour le focus est cruciale car :
- Stabilité visuelle : Modifier la bordure d'un bouton au focus pourrait ajouter 2px à sa taille totale, provoquant un léger saut visuel désagréable pour l'utilisateur.
- Indépendance : On peut conserver une bordure stylisée pour le design tout en ayant un contour d'accessibilité distinct.
3. Comment
A. Syntaxe de base
La syntaxe est similaire à celle de border.
.btn-custom {
/* Syntaxe raccourcie : width | style | color */
outline: 3px solid #005fcc;
}
B. Cas concret : Un système de focus robuste
En production, on ne se contente pas d'une couleur. On utilise outline-offset pour créer un espace entre l'élément et son contour, ce qui améliore grandement la lisibilité, surtout sur des éléments avec des fonds colorés.
/* Style de base pour tous les éléments interactifs */
.interactive-element {
border: 1px solid #ccc;
padding: 10px 20px;
background-color: white;
cursor: pointer;
transition: background-color 0.2s ease;
}
/* Focus optimisé pour l'accessibilité */
.interactive-element:focus {
/* On définit un contour épais et contrasté */
outline: 3px solid #2563eb;
/* L'offset crée un "vide" entre la bordure et l'outline */
/* Cela permet de détacher visuellement l'indicateur du composant */
outline-offset: 2px;
}
C. Limitations
L' outline a une limitation majeure : il suit généralement la forme du box-model. Bien que les navigateurs modernes supportent mieux les border-radius avec outline, certains anciens navigateurs affichaient des contours rectangulaires même sur des boutons arrondis.
Pour pallier cela, certains développeurs utilisent box-shadow, mais attention : box-shadow n'est pas toujours interprété comme un indicateur de focus par certains outils d'assistance et peut être ignoré en mode "Contraste élevé" sur Windows.
4. Zone de Danger
❌ L'erreur fatale : outline: none ou outline: 0
C'est l'erreur la plus courante. Pour des raisons esthétiques, beaucoup de développeurs suppriment le contour bleu par défaut du navigateur sans proposer d'alternative. Cela rend le site inaccessible.
✅ La bonne pratique : Remplacer, ne pas supprimer Si le style par défaut ne convient pas, créez votre propre style de focus qui respecte les ratios de contraste WCAG (minimum 3:1 pour les composants d'interface).
Logique de déclenchement des indicateurs de focus
Maîtriser :focus-visible
1. Quoi
La pseudo-classe :focus-visible est une évolution intelligente de :focus. Elle permet d'appliquer un style de focus uniquement lorsque le navigateur juge que l'indicateur est nécessaire.
En règle générale :
- Si l'utilisateur navigue avec le clavier →
:focus-visibleest actif. - Si l'utilisateur clique avec la souris →
:focus-visiblen'est pas actif (sur la plupart des éléments).
2. Pourquoi
C'est la solution au conflit historique entre designers et experts en accessibilité. Les designers détestent voir un contour apparaître lorsqu'un utilisateur clique sur un bouton avec sa souris (car le clic est déjà un indicateur visuel suffisant). Les experts en a11y exigent ce contour pour les utilisateurs clavier.
:focus-visible permet d'avoir le meilleur des deux mondes : un site esthétique pour les utilisateurs de souris et parfaitement accessible pour les utilisateurs de clavier.
3. Comment
A. Syntaxe de base
L'astuce consiste à supprimer le focus standard et à le redéfinir via :focus-visible.
/* On retire le focus pour tout le monde (attention danger !) */
.btn:focus {
outline: none;
}
/* On le remet UNIQUEMENT pour ceux qui en ont besoin (clavier) */
.btn:focus-visible {
outline: 3px solid #ffcc00;
outline-offset: 2px;
}
B. Cas concret : Composant de formulaire professionnel
Voici comment implémenter un champ de saisie qui reste discret au clic mais devient très visible à la navigation clavier.
.input-field {
border: 2px solid #ddd;
border-radius: 4px;
padding: 8px;
font-size: 1rem;
}
/*
On utilise :focus pour gérer l'état actif (ex: changement de couleur de bordure)
qui est utile pour tous les utilisateurs.
*/
.input-field:focus {
border-color: #666;
outline: none; /* On retire l'outline par défaut du navigateur */
}
/*
On utilise :focus-visible pour l'indicateur d'accessibilité critique.
L'utilisateur clavier verra ce contour, l'utilisateur souris ne le verra pas.
*/
.input-field:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.2); /* Optionnel : halo doux */
}
C. Limitations
Bien que largement supporté, :focus-visible peut avoir des comportements légèrement différents selon les navigateurs pour certains éléments spécifiques (comme les liens <a> ou les boutons). Il est recommandé de toujours tester avec la touche Tab de son clavier.
4. Zone de Danger
❌ Confondre :focus et :focus-visible
Appliquer un style complexe uniquement sur :focus-visible sans gérer :focus peut laisser l'élément sans aucun retour visuel lors d'un clic, ce qui peut être déroutant pour certains utilisateurs.
✅ La stratégie hybride
Utilisez :focus pour des changements subtils (couleur de fond, bordure) et :focus-visible pour l'indicateur de positionnement fort (outline).
Questions clés
1. Quelle est la différence fondamentale entre border et outline concernant le rendu ?
Découvrir la réponse
La border fait partie du modèle de boîte (box-model) et occupe de l'espace. Si vous changez la largeur d'une bordure au survol ou au focus, les éléments autour peuvent bouger. L' outline est dessiné "au-dessus" de l'élément, sans affecter sa taille ni la position des éléments voisins.
2. Pourquoi ne faut-il jamais utiliser outline: none seul ?
Découvrir la réponse
Parce que cela supprime l'unique indicateur visuel pour les utilisateurs naviguant au clavier. Sans cet indicateur, l'utilisateur ne sait pas quel lien ou bouton il s'apprête à activer, rendant le site inutilisable pour les personnes malvoyantes ou ayant des handicaps moteurs.
3. Comment fonctionne :focus-visible par rapport à :focus ?
Découvrir la réponse
:focus s'active dès que l'élément reçoit le focus, peu importe la méthode (clic ou clavier). :focus-visible est plus intelligent : il ne s'active que si le navigateur estime que l'utilisateur a besoin d'un indicateur visuel (généralement lors de l'utilisation du clavier).
4. Qu'est-ce que outline-offset et pourquoi est-ce utile pour l'accessibilité ?
Découvrir la réponse
outline-offset définit la distance entre le bord de l'élément et la ligne de l'outline. C'est utile car cela crée un espace blanc (ou transparent) qui permet de mieux distinguer le contour du composant, surtout si le composant a lui-même une bordure ou une couleur de fond sombre.
5. Comment garantir la visibilité du focus en mode "Contraste Élevé" (Windows High Contrast Mode) ?
Découvrir la réponse
L'utilisation de la propriété outline est la méthode la plus sûre, car le système d'exploitation peut forcer la couleur de l'outline pour garantir le contraste. Évitez de compter uniquement sur box-shadow ou des changements de couleur de fond, car ils sont souvent ignorés ou écrasés dans ce mode.
Mise en pratique
Exercice 1 : Reproduction guidée
Créez un bouton avec les caractéristiques suivantes :
- Couleur de fond bleue, texte blanc.
- Au focus, le bouton doit avoir un contour orange de 4px, avec un espacement de 3px entre le bouton et le contour.
- Le contour ne doit pas déplacer le bouton.
HTML de départ :
<button class="btn-exercise">Envoyer</button>
Découvrir la solution commentée
.btn-exercise {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-exercise:focus {
/* On utilise outline pour éviter le layout shift */
outline: 4px solid orange;
/* L'offset crée l'espace demandé */
outline-offset: 3px;
}
Exercice 2 : Adaptation avec :focus-visible
Vous avez des liens de navigation dont le focus est actuellement géré uniquement avec :focus. Problème : le contour violet apparaît aussi quand l'utilisateur clique avec la souris, ce qui est visuellement indésirable.
Objectif : Adapter le CSS pour que :
- Lorsqu'on clique avec la souris, aucun contour n'apparaisse.
- Lorsqu'on navigue avec la touche Tab, le contour violet reste bien visible.
HTML de départ :
<nav>
<a href="#" class="nav-link">Accueil</a>
<a href="#" class="nav-link">Produits</a>
<a href="#" class="nav-link">Contact</a>
</nav>
CSS de départ — à adapter :
.nav-link {
color: #333;
text-decoration: none;
padding: 5px;
}
/* PROBLÈME : le contour s'affiche aussi au clic souris */
.nav-link:focus {
outline: 3px solid purple;
outline-offset: 2px;
border-radius: 2px;
}
Ce que vous devez modifier :
- Supprimer l'
outlinedans:focus(en ajoutantoutline: none). - Déplacer le style de contour dans
:focus-visiblepour le réserver à la navigation clavier.
Découvrir la solution commentée
.nav-link {
color: #333;
text-decoration: none;
padding: 5px;
}
/*
On supprime l'outline par défaut pour tous les types de focus
afin de prendre le contrôle total.
*/
.nav-link:focus {
outline: none;
}
/*
On réactive l'indicateur UNIQUEMENT pour la navigation clavier.
L'utilisateur souris ne verra rien, l'utilisateur clavier verra le violet.
*/
.nav-link:focus-visible {
outline: 3px solid purple;
outline-offset: 2px;
border-radius: 2px;
}
Exercice 3 : Conception d'un champ de saisie accessible
Niveau : Avancé
:focus-visible sur les champs de saisieContrairement aux boutons et aux liens, les champs <input> (et <textarea>) déclenchent toujours :focus-visible, même au clic souris. C'est un comportement volontaire du navigateur : l'utilisateur doit à tout moment savoir où son curseur se trouve pour pouvoir taper. Il est donc normal et correct que le contour apparaisse au clic sur un champ de saisie.
La distinction clavier/souris de :focus-visible est pertinente sur les éléments non-texte (boutons, liens) — comme démontré dans l'exercice 2.
Concevez un champ de saisie (input) qui respecte les critères suivants :
- État normal : Bordure grise fine.
- État focus (clic et clavier) : La bordure devient bleue et un contour noir avec un halo bleu apparaît — c'est le comportement correct pour un input.
- Assurez-vous que le passage de l'état normal à l'état focus ne provoque aucun mouvement de texte ou de bordure.
HTML de départ :
<div class="form-group">
<label for="email">Adresse e-mail</label>
<input type="email" id="email" class="input-accessible" placeholder="vous@exemple.fr" />
</div>
Propriétés CSS attendues :
| Sélecteur | Propriété | Valeur attendue |
|---|---|---|
.input-accessible | border | 1px solid #ccc |
.input-accessible | padding | 8px |
.input-accessible | font-size | 16px |
.input-accessible | border-radius | 4px |
.input-accessible | transition | border-color 0.2s ease |
.input-accessible:focus | border-color | #005fcc |
.input-accessible:focus | outline | none (retire le contour navigateur par défaut) |
.input-accessible:focus-visible | outline | 2px solid black (s'affiche au clic et au clavier — comportement normal pour un input) |
.input-accessible:focus-visible | outline-offset | 2px |
.input-accessible:focus-visible | box-shadow | 0 0 0 4px rgba(0, 95, 204, 0.2) |
border: 1px solid dès le départ ?Si la bordure n'existait pas à l'état normal et apparaissait au focus, elle ajouterait 1 px à la taille du champ — déplaçant légèrement les éléments voisins. En définissant la bordure dès le départ (même transparente ou grise), seule la couleur change au focus : aucun décalage.
Découvrir la solution commentée
.input-accessible {
/* On définit une bordure initiale pour éviter le saut visuel */
border: 1px solid #ccc;
padding: 8px;
font-size: 16px;
border-radius: 4px;
transition: border-color 0.2s ease;
}
/*
Gestion du focus général : on change la couleur de la bordure.
L'épaisseur reste la même (1px) pour éviter tout décalage.
*/
.input-accessible:focus {
border-color: #005fcc;
outline: none; /* On retire l'outline navigateur pour mettre le nôtre */
}
/*
Pour les <input>, :focus-visible s'active TOUJOURS (clic ET clavier).
C'est voulu : l'utilisateur doit savoir où il tape, peu importe la méthode.
On y place notre contour personnalisé qui remplace celui du navigateur.
*/
.input-accessible:focus-visible {
/* Contour net pour le contraste */
outline: 2px solid black;
outline-offset: 2px;
/* Halo pour l'esthétique et le renfort visuel */
box-shadow: 0 0 0 4px rgba(0, 95, 204, 0.2);
}