Comment gérer la visibilité, le focus clavier et le rendu dans les technologies d’assistance des éléments de façon accessible
Avec un grand pouvoir vient une grande responsabilité
Cette célèbre réplique de l’oncle Ben Parker s’applique parfaitement au développement web.
Les outils permettant de gérer la visibilité d’un élément, son accessibilité par les technologies d’assistance ou la prise de focus au clavier sont puissants et variés. Ils doivent cependant être manipulés avec précaution pour garantir une expérience utilisateur accessible à toutes et tous.
Voici un tour d’horizon des attributs HTML et des propriétés CSS à utiliser selon la situation.
L’attribut aria-hidden="true"
Statut : visible, inaccessible aux lecteurs d’écran, mais atteignable au focus clavier.
Fonctionnement : cet attribut rend un élément visible indisponible aux technologies d’assistance, tout en lui permettant de conserver la possibilité de recevoir le focus clavier. Lorsque cet attribut est appliqué à un élément, ses enfants deviennent eux aussi indisponibles pour les technologies d’assistance.
Attention toutefois : si lui-même ou l’un de ses enfants est un élément interactif, il pourra tout de même prendre le focus clavier.
Cas d’usage : il est souvent utilisé pour masquer des éléments non porteurs d’information, comme des images décoratives ou des icônes SVG intégrées dans un bouton.
<button aria-label="Fermer"><svg aria-hidden="true">...</svg></button>
L’attribut tabindex="-1"
Statut : visible, accessible aux lecteurs d’écran, mais inatteignable au focus clavier.
Fonctionnement : cet attribut est disponible aux technologies d’assistance, mais il supprime la prise de focus clavier sur un élément interactif. Sa grande force réside dans sa capacité à permettre une prise de focus programmatique (via JavaScript avec la méthode focus()) uniquement et essentiellement sur des éléments statiques, comme un paragraphe ou un titre.
Cas d’usage : on l’utilise fréquemment pour gérer la reprise de focus lors d’un changement de contexte. Par exemple, lors de l’ouverture d’une boîte de dialogue modale, il peut être positionné sur le titre afin de déplacer le focus de façon programmatique au début du dialogue.
<div role="dialog" aria-modal="true" aria-labelledby="titre-1">
<h1 id="titre-1" tabindex="-1">Je suis le titre du dialogue</h1>
[…]
</div>
L’attribut tabindex="0"
Statut : visible, accessible aux lecteurs d’écran et atteignable au focus clavier.
Fonctionnement : sa force principale est de pouvoir donner le focus clavier à un élément statique (comme un paragraphe ou un titre). Néanmoins, en l’absence d’une sémantique adéquate d’élément interactif (role="button", role="link", etc.), l’élément sera considéré comme non-conforme. Sur un élément interactif natif HTML, il n’apporte aucune valeur ajoutée puisque cet élément peut déjà, par nature, prendre le focus clavier.
Cas d’usage : il est souvent utilisé en complément d’un rôle ARIA lorsqu’il s’avère impossible d’utiliser un élément interactif natif HTML ou encore lorsque l’on souhaite gérer la prise de focus dans un composant d’interface.
<div role="button" tabindex="0">Je suis un bouton, atteignable au clavier mais non fonctionnel en l’état</div>
L’attribut hidden
Statut : non visible, inaccessible aux lecteurs d’écran et inatteignable au focus clavier.
Fonctionnement : cet attribut masque complètement un élément et ses enfants pour tout le monde. Même si l’élément concerné est interactif, il ne pourra pas être atteint au clavier.
Cas d’usage : on y a souvent recours pour masquer un sous-menu lorsqu’il n’est pas déployé, évitant ainsi que ses éléments soient disponibles dans cet état réduit.
<button aria-expanded="false">Menu</button>
<div hidden>
<ul>
<li><a href="#">Je suis un lien non disponible à l'état réduit</a></li>
</ul>
</div>
L’attribut inert
Statut : visible, inaccessible aux lecteurs d’écran, inatteignable au focus clavier et au pointeur.
Fonctionnement : il permet de conserver le visuel d’un élément et de ses enfants tout en les rendant indisponibles aux technologies d’assistance, en interdisant la prise de focus clavier et les interactions du pointeur sur l’ensemble de ses éléments interactifs. C’est finalement une combinaison des attributs aria-hidden="true" et tabindex="-1" appliqué à l’ensemble des éléments interactifs.
Cas d’usage : cet attribut s’avère très utile dans les carrousels par exemple, plus spécifiquement sur les panneaux masqués ou partiellement masqués visuellement que l’on ne souhaite pas rendre disponibles au clavier, au pointeur et aux technologies d’assistance.
<h2 id="our-strengths">Nos points forts</h2>
<section class="carousel" aria-roledescription="Carrousel" aria-labelledby="our-strengths">
<div id="carousel-items">
<div role="group" aria-roledescription="Panneau" aria-label="1 sur 3">
<h3>Design Responsable</h3>
<p>Le Design Responsable est une démarche […] son cycle de vie.</p>
<a href="#en-savoir-plus">Découvrir les projets éco-responsables</a>
</div>
<div role="group" aria-roledescription="Panneau" aria-label="2 sur 3" inert>
<h3>Accessibilité Numérique</h3>
<p>L'Accessibilité Numérique consiste à concevoir […] personnes handicapées.</p>
<a href="#audit">Découvrir les projets accessibles</a>
</div>
[…]
</div>
</section>
L’attribut disabled
Statut : visible mais peu perceptible par défaut, accessible aux lecteurs d’écran, inatteignable au focus clavier.
Fonctionnement : il fonctionne sur les éléments interactifs natifs qui l’acceptent, comme par exemple un bouton ou un champ de formulaire. Il peut également être utilisé sur certains éléments statiques comme la balise <fieldset>. Bien que l’élément soit visible et disponible pour les technologies d’assistance, il s’avère souvent peu perceptible visuellement par défaut pour indiquer un état désactivé. Attention toutefois, si l’élément est porteur d’information, cet état devrait être perceptible visuellement. Puisque l’élément n’est pas censé être utile dans l’interface, il n’est pas atteignable au focus clavier. Ce point est à prendre en compte pour les éléments interactifs susceptibles d’être désactivés, afin d’éviter la perte de focus clavier. C’est le cas, par exemple, des boutons de contrôle de certains carrousels lorsque l’on atteint le premier ou le dernier panneau. Dans ce cas, l’usage de l’attribut aria-disabled peut être une meilleure solution (voir la section suivante).
Cas d’usage : dans un formulaire, des champs sont désactivés tant que d’autres choix n’ont pas été faits au préalable.
<input type="checkbox" id="toggle-shipping-address" name="toggle-shipping-address">
<label for="toggle-shipping-address">Adresse de livraison différente de l’adresse de facturation</label>
<fieldset>
<legend>Adresse de livraison</legend>
<label for="street-address">Nom de la voie</label>
<input type="text" id="street-address" name="street-address" autocomplete="address-line1" disabled="disabled">
[…]
</fieldset>
L’attribut aria-disabled="true"
Statut : visible, accessible aux lecteurs d’écran et atteignable au focus clavier.
Fonctionnement : à la manière de l’attribut disabled, il fonctionne également sur les éléments interactifs qui l’acceptent, mais peut aussi s’appliquer à certains composants ou éléments statiques (comme des groupes). Contrairement à son homologue natif, il n’est pas personnalisé graphiquement par défaut.
Avantage majeur : l’élément reste accessible au focus clavier. C’est un atout de taille : si un élément interactif passe à l’état désactivé, l’utilisateur conserve le focus sur l’élément sans le perdre brusquement. Il faudra bien entendu prévoir en JavaScript de désactiver l’action de l’élément à l’état désactivé et dans les formulaires de gérer manuellement les contrôles de formulaire.
Cas d’usage : comme déjà évoqué auparavant, un carrousel avec des contrôles qui peuvent changer d’état est un bon exemple.
<button type="button">Précédent</button>
<button aria-disabled="true" type="button">Suivant</button>
Les propriétés CSS display: none; et visibility: hidden;
Statut : non visible, inaccessible aux lecteurs d’écran et inatteignable au focus clavier.
Fonctionnement : ces propriétés CSS masquent complètement l’élément pour l’ensemble des utilisateurs et suppriment toute interaction au clavier. Cependant, il existe une exception notable : si l’élément masqué est ciblé par un attribut aria-labelledby ou aria-describedby, il demeure restituable par les technologies d’assistance.
Différence clé : contrairement à la propriété CSS display: none;, la propriété visibility: hidden; a l’avantage de conserver les transitions CSS.
Cas d’usage : idéal pour masquer un contenu qui n’est pas visible et non atteignable au clavier, comme un sous-menu réduit.
<button aria-expanded="false">Menu</button>
<div style="display: none;">
<ul>
<li><a href="#">Je suis un lien non disponible à l'état réduit</a></li>
</ul>
</div>
Les classes CSS pour masquer visuellement (.sr-only, .visually-hidden, etc.)
Statut : non visible, accessible aux lecteurs d’écran et atteignable au focus clavier.
Fonctionnement : l’élément n’est pas visible à l’écran car il est positionné de manière à sortir du cadre visible, ce qui lui permet de rester disponible pour les technologies d’assistance. Appliquer ce type de classe sur un élément interactif ne l’empêche pas de recevoir le focus clavier. La vigilance est de mise : cette configuration est particulièrement pertinente si l’élément se dévoile et devient visible uniquement au moment de la prise de focus (par exemple, un lien d’évitement).
Cas d’usage : très utile pour créer des noms accessibles ou fournir des informations contextuelles spécifiques aux utilisateurs de lecteurs d’écran.
<a href="#">En savoir plus<span class="sr-only"> sur la classe .sr-only</span></a>
En CSS, cette classe est généralement définie de la façon suivante :
.sr-only {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
Récapitulatif
| Éléménts | Présent visuellement | Accessible aux technologies d’assistance | Atteignable au clavier |
|---|---|---|---|
| aria-hidden="true" | Oui | Non | Oui |
| tabindex="-1" | Oui | Oui | Non |
| tabindex="0" | Oui | Oui | Oui |
| hidden | Non | Non | Non |
| inert | Oui | Non | Non |
| disabled | Oui | Oui | Non |
| aria-disabled="true" | Oui | Oui | Oui |
| display: none; visibility: hidden; |
Non | Non | Non |
| .sr-only, .visually-hidden, etc. | Non | Oui | Oui |
Article publié par
Steven MouretExpert, consultant en accessibilité numérique.



tabindex= »-1″ appliqué sur le titre d’une modale est en réalité une mauvaise pratique d’accessibilité.
La bonne pratique serait plutôt de focus un élément interactif dans la modale, comme le premier input présent, ou le premier bouton présent.
Bonjour Cédric, n’hésitez pas à nous en dire plus sur cette mauvaise pratique.
Le déplacement du focus sur un élément dans un dialogue modal peut être variable en fonction de son contexte mais également en fonction des différentes personnes concernées. Ce sujet est loin d’être simple et je ne pense pas qu’il y ait une solution universelle. L’exemple cité vise principalement à illustrer la gestion du focus clavier vers un élément statique.