Skip to Content

Chapitre 4.5 — Pièges & contenu masqué

⏱️ TL;DR — Un piège au clavier (WCAG 2.1.2), c’est un endroit où le focus entre mais ne peut plus sortir : une modale sans Échap, un widget qui capture Tab. À éviter absolument. L’autre grande source de bugs, c’est le contenu masqué : toutes les façons de « cacher » ne se valent pas. display:none et l’attribut hidden retirent l’élément (non focusable, non lu) ; visibility:hidden aussi ; la classe .sr-only cache visuellement mais laisse lire et focuser ; aria-hidden="true" cache du lecteur d’écran mais laisse focuser (danger !) ; et l’attribut inert neutralise tout (ni interaction, ni focus, ni lecture) sur une zone.

🎯 Objectifs

  • Reconnaître et éviter un piège au clavier (critère 2.1.2).
  • Distinguer les techniques de masquage : display:none, hidden, visibility:hidden, .sr-only, aria-hidden, inert.
  • Comprendre le piège du focusable dans une zone aria-hidden.
  • Utiliser inert pour neutraliser proprement une zone (arrière-plan d’une modale).

Le piège au clavier (2.1.2)

Le critère WCAG 2.1.2 (Pas de piège au clavier), niveau A, complète le 2.1.1 : non seulement tout doit être atteignable au clavier, mais on doit aussi pouvoir en repartir. Si le focus entre dans un composant et ne peut plus en sortir au Tab (ni avec une touche standard documentée), c’est un piège — l’utilisateur clavier est bloqué, parfois obligé de recharger la page.

Les coupables classiques :

  • La modale sans sortie : pas de Échap, pas de bouton « Fermer » atteignable → l’utilisateur reste prisonnier.
  • Le widget tiers qui capture Tab : un lecteur vidéo, un éditeur de texte riche, une carte interactive mal codés qui « avalent » la touche Tab sans jamais la relâcher.
  • Le focus trap mal fait : le Chapitre 4.4 a montré qu’un piège de focus légitime (retenir le focus dans une modale ouverte) devient illégitime dès qu’il n’offre aucune issue.

⚠️ Piège — La nuance est fine mais capitale : retenir le focus dans une modale ouverte est voulu (focus trap) ; emprisonner le focus sans issue est interdit (2.1.2). La différence tient à une seule chose : une porte de sortie toujours disponibleÉchap, un bouton « Fermer », ou la fermeture qui rend le focus au déclencheur. Un piège de focus sans Échap, c’est un piège au clavier.

Cacher un contenu : cinq techniques, cinq effets

« Masquer » un élément est ambigu : le cacher à l’œil, au lecteur d’écran, au clavier — ce sont trois questions distinctes, et chaque technique répond différemment. C’est la source de confusion de ce chapitre. Le tableau qui suit est à mémoriser.

TechniqueVisible à l’écran ?Lu par le lecteur d’écran ?Focusable au clavier ?
display: none❌ non❌ non❌ non
Attribut hidden❌ non❌ non❌ non
visibility: hidden❌ non (garde la place)❌ non❌ non
Classe .sr-only (visually-hidden)❌ nonouioui
aria-hidden="true"oui❌ nonoui (⚠️)
Attribut inert✅ oui❌ non❌ non

display:none et l’attribut hidden — le vrai « retiré »

display: none (CSS) et l’attribut HTML hidden (qui applique display:none par défaut) retirent totalement l’élément : invisible, non lu par le lecteur d’écran, non focusable. C’est ce que tu veux pour du contenu réellement absent (un panneau d’accordéon fermé, par exemple). Bonus : un élément en display:none sort automatiquement de l’ordre de tabulation — pas de focus fantôme.

visibility:hidden — caché mais réserve la place

visibility: hidden cache l’élément tout en gardant son espace dans la mise en page. Comme display:none, il le rend non lu et non focusable. Utile quand tu veux masquer sans faire « bouger » la page.

.sr-only — pour le lecteur d’écran uniquement

La classe utilitaire .sr-only (ou visually-hidden) fait l’inverse : elle cache l’élément à l’œil mais le laisse dans l’arbre d’accessibilité — donc lu par le lecteur d’écran. C’est la technique pour fournir un texte destiné uniquement aux utilisateurs de lecteur d’écran (une précision de contexte, un libellé). On la détaille en Partie 6.

/* La classe .sr-only : invisible à l'œil, présente pour le lecteur d'écran */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

Attention : comme l’élément reste dans le DOM, tout élément interactif placé à l’intérieur reste focusable — donc le focus peut « atterrir » sur un élément invisible. C’est voulu et utile pour un skip link (qui se révèle au focus, Chapitre 4.4), mais c’est un bug si tu y laisses traîner des contrôles que tu croyais « cachés ».

aria-hidden="true" — caché du lecteur d’écran seulement

aria-hidden="true" retire l’élément (et ses descendants) de l’arbre d’accessibilité : le lecteur d’écran l’ignore. Mais — point crucial — l’élément reste visible à l’écran et surtout reste focusable au clavier. C’est fait pour masquer du décoratif (une icône redondante, du contenu dupliqué) au lecteur d’écran.

⚠️ Piège — Le pire scénario : un élément focusable (<button>, <a>, <input>) à l’intérieur d’une zone aria-hidden="true". Au Tab, l’utilisateur clavier atterrit dessus… mais le lecteur d’écran, lui, l’ignore : la personne a le focus sur un élément dont son outil ne dit rien. Focus « fantôme », désorientation totale. Règle : ne mets jamais aria-hidden="true" sur (ou autour d’)un élément focusable. Si tu veux vraiment neutraliser une zone qui contient des éléments interactifs, utilise inert, pas aria-hidden.

<!-- ❌ Le bouton est focusable au Tab, mais invisible pour le lecteur d'écran : focus fantôme --> <div aria-hidden="true"> <button type="button">Fermer</button> </div>
<!-- ✅ inert neutralise TOUT : le bouton n'est ni focusable, ni lu, ni cliquable --> <div inert> <button type="button">Fermer</button> </div>

inert — neutraliser une zone entière

L’attribut HTML inert est l’outil propre pour neutraliser une portion de page : les éléments à l’intérieur deviennent non focusables, non cliquables et retirés de l’arbre d’accessibilité (comme un aria-hidden implicite). Ils restent visibles, mais totalement inactifs.

Son usage vedette : l’arrière-plan d’une modale. Plutôt que de coder un focus trap manuel (voir Chapitre 4.4), on rend tout le reste de la page inert pendant que la modale est ouverte. Le focus ne peut alors pas en sortir : il n’y a plus rien de focusable en dehors de la modale.

// ✅ Pattern moderne : neutraliser l'arrière-plan pendant la modale function ouvrirModale() { pageArrierePlan.inert = true; // tout l'arrière-plan devient inactif modale.hidden = false; modale.focus(); } function fermerModale() { modale.hidden = true; pageArrierePlan.inert = false; // on réactive l'arrière-plan declencheur?.focus(); }

🧭 Sur A11yLearn — Sur A11yLearn, la modale « Terminer le quiz ? » avait un double bug. D’abord, aria-hidden="true" était posé sur le <main> derrière la modale — mais le <main> contenait encore des boutons focusables : au Tab, le focus filait sur des boutons muets pour le lecteur d’écran (focus fantôme). Ensuite, aucune touche Échap : une fois entré, impossible de sortir sans la souris (piège au clavier, 2.1.2). On a corrigé les deux d’un coup : inert sur l’arrière-plan (au lieu d’aria-hidden), ce qui rend tout le reste non focusable et non lu, plus Échap qui referme et rend le focus au bouton « Terminer ».

✏️ Exercices

Exercice 1 — Corrige le focus fantôme. Pendant qu’une modale est ouverte, un développeur a masqué le contenu de fond ainsi. Explique le bug et propose mieux.

<main aria-hidden="true"> <a href="/accueil">Accueil</a> <button type="button">Profil</button> </main>

✅ Solution

aria-hidden="true" retire le <main> de l’arbre d’accessibilité (le lecteur d’écran l’ignore) mais le lien et le bouton restent focusables : en tabulant, l’utilisateur clavier tombe sur des éléments dont le lecteur d’écran ne dit rien — focus fantôme. La bonne solution est inert, qui neutralise à la fois le focus, le clic et la lecture :

<main inert> <a href="/accueil">Accueil</a> <button type="button">Profil</button> </main>

Ainsi, tant que la modale est ouverte, rien du fond n’est ni focusable ni lu — le focus reste naturellement dans la modale.

Exercice 2 — Bon outil, bon besoin. Pour chacun, choisis la technique de masquage : (a) un panneau d’accordéon fermé qu’on ne veut ni voir, ni lire, ni tabuler ; (b) un texte « Ouvre dans un nouvel onglet » réservé aux lecteurs d’écran ; (c) neutraliser la page derrière une modale ouverte.

✅ Solution

(a) display: none (ou l’attribut hidden) : le contenu fermé doit être totalement retiré — invisible, non lu, non focusable. (b) La classe .sr-only : caché à l’œil mais lu par le lecteur d’écran. (c) L’attribut inert sur le reste de la page : non focusable, non cliquable, non lu, tant que la modale est ouverte. Trois besoins, trois techniques — d’où l’importance du tableau récapitulatif.

🧠 Quiz de révision

1. Qu’est-ce qu’un piège au clavier, et quel critère l’interdit ?

C’est un endroit où le focus entre mais ne peut plus sortir au clavier (modale sans Échap, widget qui capture Tab). Il est interdit par le critère 2.1.2 (Pas de piège au clavier), niveau A. Il faut toujours une issue : Échap, bouton « Fermer », etc.

2. Un élément en display:none est-il focusable ?

Non. display: none (comme l’attribut hidden et visibility: hidden) retire l’élément : invisible, non lu par le lecteur d’écran, non focusable. Il sort automatiquement de l’ordre de tabulation — pas de focus fantôme.

3. Quelle différence entre .sr-only et aria-hidden=“true” ?

Ils sont opposés. .sr-only cache à l’œil mais laisse lire par le lecteur d’écran (pour du texte réservé aux TA). aria-hidden="true" cache du lecteur d’écran mais laisse visible à l’écran (pour du décoratif). Attention : les deux laissent focusable un élément interactif à l’intérieur.

4. Pourquoi ne jamais mettre aria-hidden=“true” autour d’un élément focusable ?

Parce que l’élément reste focusable au Tab alors que le lecteur d’écran l’ignore : l’utilisateur clavier atterrit sur un contrôle dont son outil ne dit rien — un focus fantôme désorientant. Pour neutraliser une zone interactive, utilise inert, pas aria-hidden.

5. Que fait l’attribut inert ?

Il neutralise toute une zone : les éléments à l’intérieur deviennent non focusables, non cliquables et retirés de l’arbre d’accessibilité (donc non lus), tout en restant visibles. C’est l’outil propre pour désactiver l’arrière-plan d’une modale ouverte, sans focus fantôme ni piège.


Partie suivante : Partie 5 — Lecteurs d’écran & arbre d’accessibilité — comment ces outils lisent réellement ta page, et le triptyque nom / rôle / valeur.

Last updated on