outline: none ne figurait nulle part dans la feuille de style du composant incriminé. Pourtant, sur un téléphone à petit écran, le contour de focus d’un lien de navigation devenait totalement invisible à la navigation clavier ou au parcours au doigt avec VoiceOver activé sur iOS. Le diagnostic a demandé plus de temps que prévu, car la cause ne se trouvait dans aucune règle visant directement le focus.
Le composant en question, un fil d’Ariane horizontal, utilisait deux fonctionnalités CSS modernes tout à fait légitimes prises séparément : padding-inline avec une valeur calculée par clamp() pour réduire l’espacement progressivement sur petit écran, et overflow-x: hidden sur le conteneur parent pour éviter un débordement horizontal disgracieux sur les fils d’Ariane longs.
Le code en cause
.fil-ariane {
overflow-x: hidden;
white-space: nowrap;
}
.fil-ariane a {
padding-inline: clamp(0px, 2vw - 4px, 12px);
}
La fonction clamp(0px, 2vw - 4px, 12px) calcule une valeur qui descend jusqu’à zéro dès que la largeur de viewport passe sous 200 pixels de calcul intermédiaire, ce qui, avec les marges du site, se produisait concrètement en dessous de 360 pixels de large sur un téléphone d’entrée de gamme. Le padding s’annulait alors complètement autour des liens du fil d’Ariane.
Pourquoi l’annulation du padding suffit à casser le focus

Le contour de focus par défaut du navigateur (outline) se dessine autour de la boîte de l’élément, débordant légèrement au-delà de son padding. Quand le padding devient nul, l’élément lien se réduit à la largeur exacte de son texte, sans marge de respiration. Combiné à overflow-x: hidden sur le conteneur parent, le débordement du contour de focus au-delà de cette boîte réduite se retrouvait coupé net par la troncature du parent, exactement comme le serait un élément visuellement débordant.
Le résultat observé au clavier : le focus se déplaçait bien d’un lien à l’autre (vérifiable en lisant la barre d’état du navigateur ou l’annonce du lecteur d’écran), mais rien ne le signalait visuellement. Le critère WCAG 2.4.7 « Focus visible », introduit en WCAG 2.0 niveau AA, exige qu’un indicateur de focus clavier soit visible ; ici, il existait dans le DOM et dans le moteur de rendu, mais se retrouvait rogné à l’affichage par une combinaison d’effets de bord entre deux propriétés indépendantes.
Comment confirmer le diagnostic
- Réduire la largeur de la fenêtre du navigateur jusqu’au point de rupture suspecté, ici 360 pixels
- Inspecter l’élément focalisé dans les outils de développement et lire la valeur calculée de
padding-inline, qui affichait 0px - Désactiver temporairement
overflow-x: hiddensur le conteneur parent pour vérifier si le contour réapparaît, même partiellement débordant - Confirmer que le contour existe bien dans le DOM en inspectant l’élément actif via
document.activeElementdans la console
Le correctif appliqué
.fil-ariane a {
padding-inline: clamp(4px, 2vw - 4px, 12px);
}
.fil-ariane a:focus-visible {
outline-offset: 2px;
}
Fixer un plancher de 4 pixels dans clamp() garantit un minimum d’espace autour du texte du lien, quelle que soit la largeur de viewport, suffisant pour que le contour de focus dispose d’une zone de dessin non tronquée par le conteneur parent. L’ajout de outline-offset renforce la lisibilité du contour sans dépendre uniquement du padding du lien.
Prévenir la récidive
- Ne jamais laisser une fonction
clamp()atteindre zéro sur une propriété qui conditionne l’espace disponible pour un indicateur visuel - Tester systématiquement le focus clavier à la largeur d’écran minimale prise en charge par le design, pas uniquement en desktop
- Se méfier de toute combinaison
overflow: hiddenet élément focalisable proche du bord du conteneur
Notre réflexe désormais : chaque fois qu’un plancher de
clamp()est fixé à zéro, on se demande explicitement ce que cela signifie pour le focus visible, pas seulement pour l’esthétique de l’espacement.
En résumé
Le bug ne venait d’aucune règle ciblant directement outline ou :focus, ce qui explique la difficulté du diagnostic initial. Deux fonctionnalités CSS modernes, utilisées séparément pour des raisons parfaitement valables, produisaient ensemble un effet de bord invisible à l’œil sur desktop et bloquant sur mobile. La prévention tient en une règle simple : tout plancher calculé qui peut atteindre zéro sur une propriété d’espacement mérite d’être vérifié à l’écran le plus étroit pris en charge, avec un vrai test clavier, pas seulement une relecture du CSS.