RGAA Lab

Composants accessibles

Le fil d'Ariane

Un fil d'Ariane, c'est une liste de liens dans une région nommée — et des séparateurs que personne ne doit entendre. Le RGAA en demande moins qu'on ne croit, et pas là où on l'attend. Démo, code, critères RGAA.

4 critères RGAA en jeu

Essayez-le

Le fil balisé

Le même, bricolé

Les deux fils sont identiques à l’œil. Tabulez : le focus s’arrête sur les mêmes liens, dans le même ordre — rien ne les distingue non plus au clavier. Puis activez le bouton : il lit le DOM des deux et montre ce qui les sépare, à commencer par la barre oblique que le second donne à lire.

Cette démo existe aussi en page autonome.

L’erreur courante

Une ligne de liens dans un div, avec les séparateurs écrits en clair.

<!-- À ne pas faire -->
<div class="fil-ariane">
	<a href="/">Accueil</a> /
	<a href="/composants">Composants</a> /
	<a href="/composants/fil-d-ariane">Le fil d'Ariane</a>
</div>

La barre oblique est du texte comme le reste. Selon le niveau de ponctuation configuré dans le lecteur d’écran, elle est prononcée : « Accueil, barre oblique, Composants, barre oblique… ». Trois mots parasites pour trois étapes, et rien qui indique qu’il s’agit d’un chemin.

Le div, lui, coûte deux choses. Le fil n’est pas un repère de navigation : il n’apparaît pas quand on demande la liste des régions, et il faut le trouver en lisant la page. Et ce n’est pas une liste : ni « 3 éléments », ni « 2 sur 3 », ni le raccourci qui permet d’en sortir d’un geste.

Trois variantes de la même famille :

  • Le nav sans nom. Deux régions annoncées « navigation » dans la même page, sans rien pour dire laquelle est le menu et laquelle est le fil : la liste des repères devient inutilisable.
  • Le chevron en <svg> laissé visible aux technologies d’assistance. Il s’annonce « image » entre chaque étape — et s’il porte un <title>, c’est ce titre qui est lu, souvent « chevron droit ».
  • Le dernier élément sans aria-current. Il est en gras, donc l’œil sait qu’on y est. À l’écoute, c’est un lien comme les deux autres.

Le code, pas à pas

1. Une région, parce que c’en est une

<nav aria-label="Fil d'Ariane"></nav>

Le critère 9.2 demande que les zones de navigation principales et secondaires soient structurées par une balise <nav> — et, dans le même test, que <nav> reste réservé à ces zones. Un fil d’Ariane est une navigation secondaire : il entre dans la première moitié de la règle.

Le nom, lui, n’est exigé par aucun critère. Il devient nécessaire dès qu’une page porte plusieurs <nav> : c’est la seule chose qui les distingue dans la liste des repères. Écrivez le nom seul, sans y remettre la nature : aria-label="Navigation fil d'Ariane" s’annonce « Navigation fil d’Ariane, navigation ».

2. Une liste, et de préférence ordonnée

<nav aria-label="Fil d'Ariane">
	<ol role="list">
		<li><a href="/">Accueil</a></li>
		<li><a href="/composants">Composants</a></li>
		<li><a href="/composants/fil-d-ariane" aria-current="page">Le fil d'Ariane</a></li>
	</ol>
</nav>

Une suite d’étapes alignées et séparées est une information regroupée visuellement sous forme de liste. Le critère 9.3 se dédouble alors : le test 9.3.1 vise les listes non ordonnées et attend <ul> et <li>, le test 9.3.2 les listes ordonnées et attend <ol> et <li> — dans les deux cas, les attributs WAI-ARIA role="list" et role="listitem" sont l’autre voie acceptée. C’est la forme visuelle qui désigne le test applicable ; ce qu’aucun des deux n’admet, c’est l’absence de liste.

<ol> parce que l’ordre est ici la hiérarchie du site : l’étape 1 contient l’étape 2. Le lecteur annonce alors « 2 sur 3 », qui devient une information et non un décompte.

role="list" s’ajoute dès que les puces sont retirées, ce qui est toujours le cas ici. Ce n’est pas une exigence du référentiel — c’est la parade au rôle de liste perdu sur Safari avec VoiceOver, détaillée dans la fiche des listes.

3. Les séparateurs, que personne ne doit entendre

Deux techniques tiennent, et elles ne se valent pas tout à fait.

/* Le séparateur n'est pas dans le document : il est dessiné. */
.fil-ariane li + li::before {
	content: '›';
	margin: 0 0.5rem;
	color: var(--gris);
}
<!-- Ou : un élément réel, explicitement ignoré. -->
<li><span aria-hidden="true"></span> <a href="/composants">Composants</a></li>

Le pseudo-élément CSS est le plus propre : le caractère n’existe pas dans le document, et rien n’a à être masqué. Sa limite est connue — VoiceOver restitue le contenu généré en CSS, c’est ce qui fait lire les polices d’icônes. Si vos essais le confirment, repassez à la seconde forme : un <span> porteur de aria-hidden="true" ne laisse aucun doute sur son sort, quel que soit le lecteur.

Si le séparateur est une icône, c’est une image de décoration au sens du critère 1.2, et le test attend alors précisément ceci :

<svg aria-hidden="true" focusable="false" width="8" height="8"></svg>

aria-hidden="true" et aucune alternative : pas de <title>, pas de <desc>, pas d’attribut title. Le focusable="false" règle un problème distinct — sous Internet Explorer et certains rendus, un <svg> prend le focus sans lui.

4. aria-current="page" sur la dernière étape

<a href="/composants/fil-d-ariane" aria-current="page">Le fil d'Ariane</a>

C’est ce qui fait annoncer « page actuelle ». La valeur compte : page désigne la page courante dans un ensemble de liens, là où true ne dit que « l’élément courant » sans préciser de quoi. aria-current="page" sur autre chose qu’un lien reste permis, mais son annonce est plus régulière sur un lien.

Le dernier élément peut aussi n’être qu’un texte, sans lien. Les deux formes existent ; le lien vers la page courante a l’avantage d’être copiable et partageable, et c’est celui que retient le motif de l’ARIA APG.

5. Avez-vous besoin d’un fil d’Ariane ?

Il n’y a aucun critère du RGAA qui en exige un. La règle WCAG qu’il sert — 2.4.8 Location — est de niveau AAA, et le référentiel ne transpose que les niveaux A et AA.

Ce qu’il déclenche, en revanche, c’est le critère 12.2 : le glossaire range le fil d’Ariane parmi les barres de navigation, qui doivent se trouver toujours à la même place dans la présentation et dans le même ordre relatif dans le code source. Un fil qui apparaît sur certains gabarits et pas sur d’autres, ou qui passe au-dessus du titre ici et en dessous là, crée une non-conformité qui n’existerait pas sans lui.

Et il ne compte pas comme un des deux systèmes de navigation du critère 12.1 : le glossaire n’en retient que quatre — menu principal, table des matières, plan du site, moteur de recherche. C’est l’erreur d’analyse la plus fréquente sur ce composant ; la fiche du critère 12.1 la détaille.

Enfin, un fil d’Ariane décrit la hiérarchie du site, pas le chemin parcouru. S’il retrace l’historique, il double le bouton « précédent » du navigateur et ment sur l’arborescence.

Au clavier

Un fil d’Ariane n’a aucun comportement propre : il n’est fait que de liens, et seuls eux entrent dans l’ordre de tabulation. Sa navigation appartient au lecteur d’écran.

ToucheEffet
TabPasse au lien suivant du fil, dans l’ordre du chemin. La dernière étape en fait partie si c’est un lien.
D (NVDA) / R (JAWS)Va au repère suivant. Le <nav> du fil en est un ; son nom est ce qui le distingue du menu principal.
LVa à la liste suivante, annoncée avec son nombre d’éléments.

Ce que le lecteur d’écran restitue

À l’entrée dans la région, puis sur chaque étape : « Fil d’Ariane, navigation, liste de 3 éléments, Accueil, lien, 1 sur 3… Le fil d’Ariane, lien, page actuelle, 3 sur 3 ». La formulation varie d’un lecteur à l’autre ; les informations, non.

Le diagnostic se fait par soustraction :

  • « barre oblique » ou « image » entre deux étapes : les séparateurs ne sont ni en CSS ni masqués.
  • Aucun nom avant « navigation », ou pas de mention de région du tout : le <nav> n’est pas nommé, ou c’est un div.
  • Pas de « 1 sur 3 » : il n’y a pas de liste, ou un élément s’est glissé entre la liste et ses <li>.
  • Rien sur la dernière étape : aria-current manque.

Checklist

  • Un <nav> autour du fil, avec un nom qui ne répète pas « navigation ».
  • Une liste — <ol>, puisque l’ordre est la hiérarchie — et role="list" si les puces sont retirées.
  • Des <li> enfants directs de la liste, rien entre les deux.
  • Les séparateurs hors du texte : pseudo-élément CSS, ou aria-hidden="true".
  • Un séparateur en <svg> masqué, <title> et <desc> compris.
  • aria-current="page" sur la dernière étape — la valeur page, pas true.
  • La même place et le même rang dans le code source sur toutes les pages.
  • Le chemin reflète l’arborescence du site, pas l’historique de navigation.

Les critères RGAA en jeu

  • Critère 9.2 — Cohérence de la structure du document

    Un fil d'Ariane est une zone de navigation secondaire : le référentiel demande qu'elle soit structurée par une balise nav, et un div stylé la fait disparaître de la liste des régions de la page.

  • Critère 9.3 — Structure des listes

    Une suite de liens séparés par des chevrons est un groupement visuel en liste : sans balisage de liste, ni le nombre d'étapes ni le rang de chacune ne sont restitués.

  • Critère 1.2 — Images décoratives ignorées

    Le séparateur dessiné en svg ou en img est une image de décoration : sans aria-hidden, il s'annonce entre chaque étape, et son titre encore plus.

  • Critère 12.2 — Place constante du menu

    Le glossaire du référentiel range le fil d'Ariane parmi les barres de navigation : dès qu'il existe, il doit occuper la même place et le même rang dans le code source sur toutes les pages.

Vérifiez votre composant avec l'extension

Pour aller plus loin

Sources