Le fil, le labyrinthe et le stepper
Table des matières
Le fil de laine
Ariane ne s'est pas battue contre le Minotaure. Elle a fait mieux : elle a donné à Thésée un fil.
Un simple fil de laine, déroulé à l'entrée du Labyrinthe, pour qu'il retrouve la sortie après le combat. Le héros, c'est Thésée. Mais sans le fil, il serait mort dans un couloir.
Sur le web, le labyrinthe existe aussi. Un catalogue à 4 niveaux de profondeur. Un tunnel de paiement en 5 étapes. Un site institutionnel où chaque clic t'enfonce un peu plus loin dans l'arborescence. Et quand tu veux remonter, retour, retour, retour. Tu croises les doigts pour que le navigateur se souvienne du bon chemin.
Le fil d'Ariane, sur le web, c'est la même idée : un repère visible qui te montre où tu es et te permet de remonter sans te perdre. Sauf que sur la majorité des sites, il n'existe tout simplement pas. Pas mal codé, absent. Et pour une personne atteinte d'amnésie antérograde, qui ne retient pas le chemin qu'elle vient de parcourir, chaque page sans fil d'Ariane est un couloir sans issue.
Cet article couvre deux patterns de navigation que tout le monde confond : le fil d'Ariane (breadcrumb), qui montre d'où tu viens dans une hiérarchie. Et le stepper, qui montre où tu en es dans un processus. Mêmes balises, ARIA similaire, intentions opposées.
Le problème
Ferme les yeux et imagine : tu cherches une paire de baskets sur un site e-commerce. Tu es passé par "Chaussures", puis "Baskets", puis "Homme", puis un filtre "Blanc", puis tu as ouvert une fiche produit. Cinq niveaux de profondeur. Maintenant tu veux revenir aux baskets blanches pour comparer un autre modèle.
Tu appuies sur "Retour". Le filtre a disparu. Tu réappuies. Tu es sur la page d'accueil. Le chemin que tu avais dans la tête, celui que tu viens de parcourir, n'existait nulle part sauf dans ta mémoire.
Maintenant imagine la même situation, mais tu ne peux pas compter sur ta mémoire.
Pour une personne avec un trouble de l'attention, la moindre notification a suffi à effacer le contexte. Pour une personne qui utilise un lecteur d'écran, la page est un flux linéaire sans aucun repère spatial. Pas de colonne latérale, pas de chapeau visuel qui dit "tu es ici". Pour toi sur mobile, la navigation principale est pliée dans un menu burger à trois clics de distance.
Le fil d'Ariane résout ce problème en une ligne. Il ne dépend pas de l'historique du navigateur qui est fragile, surtout dans les applications modernes qui manipulent les états. Il reflète ta position dans la hiérarchie du site, pas le chemin que tu as pris pour y arriver. C'est un GPS, pas un rétroviseur.
Le fil d'Ariane (breadcrumb)
Ce que c'est
Le fil d'Ariane est une navigation secondaire. Il ne remplace pas le menu principal, il le complète. Son rôle : montrer ta position dans la hiérarchie du site et te permettre de remonter d'un ou plusieurs niveaux en un clic.
Tu le reconnais : c'est cette ligne discrète en haut de page. "Accueil > Chaussures > Baskets > Air Max 90", que tu ne regardes presque jamais, sauf quand tu en as besoin. Et quand tu en as besoin, il n'y a rien d'autre qui fasse le travail.
Utilise un fil d'Ariane quand ton site a une hiérarchie de plus de deux niveaux. Un catalogue produit, une documentation technique, un intranet par départements. Dès que l'utilisateur peut s'enfoncer dans l'arborescence, il a besoin d'un fil pour remonter.
Ne l'utilise pas sur un dashboard, une landing page ou un blog à plat. Si ta structure est linéaire ou tient sur un seul niveau, le breadcrumb n'apporte rien, il encombre.
Le HTML sémantique
Quatre balises suffisent. Pas de <div>, pas de role="navigation", pas de JavaScript.
<nav aria-label="Fil d'Ariane">
<ol>
<li><a href="/">Accueil</a></li>
<li><a href="/chaussures">Chaussures</a></li>
<li><a href="/chaussures/baskets">Baskets</a></li>
<li><a href="/chaussures/baskets/air-max" aria-current="page">Air Max 90</a></li>
</ol>
</nav>Décomposons.
<nav> : C'est une navigation. Le navigateur et les lecteurs d'écran le savent immédiatement. aria-label="Fil d'Ariane" permet de la distinguer de la navigation principale quand il y a plusieurs <nav> dans la page. Pas besoin d'ajouter role="navigation", c'est le rôle implicite de <nav>, le doubler est redondant.
<ol> : Une liste ordonnée, pas <ul>. L'ordre compte, "Accueil" vient avant "Chaussures" qui vient avant "Baskets". Cette hiérarchie est sémantique. Un lecteur d'écran annonce "liste, 4 éléments" et numérote chaque item. Avec <ul>, tu perds cette information.
<a> : Chaque niveau est un lien, y compris le dernier. Le dernier élément porte aria-current="page". Le lecteur d'écran annonce "Air Max 90, lien, page courante". L'utilisateur sait exactement où il est sans ambiguïté.
navigation, Fil d'Ariane liste, 4 éléments
- Accueil, lien
- Chaussures, lien
- Baskets, lien
- Air Max 90, lien, page courante
Les séparateurs
Entre "Accueil" et "Chaussures", tu vois un petit chevron. Il te dit "et puis". C'est un repère visuel, rien de plus. Il ne porte aucune information que la liste ordonnée ne porte déjà.
Pourtant, la majorité des implémentations collent le séparateur directement dans le HTML :
<!-- Le lecteur d'écran annonce :
« Accueil, lien, supérieur à, Chaussures, lien, supérieur à... » -->
<li><a href="/">Accueil</a> ></li>
<li><a href="/chaussures">Chaussures</a> ></li>"Supérieur à". À chaque niveau. Pour une personne qui utilise un lecteur d'écran, c'est comme si quelqu'un te répétait "et puis" entre chaque mot d'une phrase. Tu comprends, mais c'est épuisant.
La solution : le séparateur est du CSS, pas du HTML.
nav[aria-label="Fil d'Ariane"] ol {
display: flex;
flex-wrap: wrap;
list-style-type: "";
}
nav[aria-label="Fil d'Ariane"] li + li::before {
content: "›" / "";
margin-inline: var(--space-2);
}Un caractère typographique en CSS, qui n'entre pas dans le calcul du nom accessible des liens, adapté automatiquement au dark mode grâce à currentColor, et compatible forced-colors sans aucun effort. Les lecteurs d'écran modernes lisent le contenu CSS généré : c'est la syntaxe de texte alternatif vide, content: "›" / "", qui rend le séparateur réellement silencieux. Zéro SVG, zéro image, zéro bruit. Et flex-wrap: wrap permet au fil de passer à la ligne sur petit écran au lieu de déborder.
Un effet de bord connu : avec list-style: none, Safari retire la sémantique de liste, et VoiceOver n'annonce plus "liste, 4 éléments". La parade reste dans le CSS : déclarer un marqueur vide avec list-style-type: "" (ou un espace sans chasse, "\200B") masque les puces sans toucher à la sémantique. L'alternative, role="list" sur le <ol>, fonctionne aussi, mais pourquoi sortir le scalpel quand le CSS suffit.
Schema.org — BreadcrumbList
Le fil d'Ariane ne sert pas qu'aux humains. Les moteurs de recherche et les LLM l'utilisent pour comprendre la structure de ton site, et pour l'afficher directement dans les résultats.
Tu as sûrement déjà vu ça dans Google : au lieu d'une URL brute sous le titre, un chemin lisible. "exemple.com › Chaussures › Baskets". C'est le breadcrumb schema.org en action.
Ajoute un bloc JSON-LD dans la page, à côté de ton <nav> :
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Accueil",
"item": "https://example.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Chaussures",
"item": "https://example.com/chaussures"
},
{
"@type": "ListItem",
"position": 3,
"name": "Baskets",
"item": "https://example.com/chaussures/baskets"
},
{
"@type": "ListItem",
"position": 4,
"name": "Air Max 90",
"item": "https://example.com/chaussures/baskets/air-max"
}
]
}
</script>Trois bénéfices :
- SERP : Google affiche le chemin lisible au lieu de l'URL brute
- GEO : les LLM exploitent les données structurées pour situer ta page dans une hiérarchie thématique
- Cohérence : le JSON-LD est une source de vérité séparée du HTML, facile à générer côté serveur
Pour aller plus loin sur l'impact du balisage structuré pour les LLM, voir Comment le GEO force l'accessibilité web.
Les erreurs classiques
<ul> au lieu de <ol>L'ordre compte. "Accueil" est le niveau 1, "Chaussures" le niveau 2. Avec <ul>, le lecteur d'écran annonce une liste, mais sans numérotation, la hiérarchie disparaît.
<nav>Sans <nav>, le fil d'Ariane est un bloc de liens anonyme. Un lecteur d'écran ne peut pas l'identifier comme une navigation. L'utilisateur ne peut pas sauter directement dessus. Il doit parcourir toute la page pour le trouver.
aria-current oubliéSans aria-current="page", rien ne distingue le dernier lien des autres. Visuellement, tu peux le styler en gras ou en gris. Mais pour un lecteur d'écran, c'est juste un lien de plus dans la liste.
aria-label manquantUn site a souvent plusieurs <nav>, le menu principal, le menu footer, le fil d'Ariane. Sans aria-label, un lecteur d'écran annonce "Navigation" trois fois sans distinction. Avec aria-label="Fil d'Ariane", il annonce "navigation, Fil d'Ariane". L'utilisateur sait où il est.
Si ton fil d'Ariane est rendu côté client par un framework, il n'existe pas tant que le JavaScript n'a pas tourné. Un crawleur qui ne l'exécute pas ne voit rien. Un navigateur dont le JS échoue ne voit rien. Le fil d'Ariane est du contenu statique, il doit être dans le HTML initial.
Le stepper
Ce que c'est
Le stepper ressemble au fil d'Ariane. Mêmes balises, même structure. Mais l'intention est opposée.
Le fil d'Ariane montre ta position dans une hiérarchie, comme un arbre. Tu peux sauter à n'importe quel niveau. Le stepper montre ta position dans un processus, comme une ligne droite. Tu avances, tu reviens, mais tu ne sautes pas.
Tu le croises dans les tunnels de commande, les formulaires d'inscription, les assistants de configuration. Partout où il y a des étapes à suivre dans l'ordre.
<nav aria-label="Progression de la commande">
<ol>
<li><a href="/panier">Panier</a></li>
<li><a href="/livraison">Livraison</a></li>
<li><a aria-current="step" href="/paiement">Paiement</a></li>
<li>Confirmation</li>
</ol>
</nav>Trois différences avec le breadcrumb :
aria-current="step" au lieu de "page". Le lecteur d'écran annonce "Paiement, lien, étape courante". L'utilisateur sait qu'il est dans un processus, pas dans une arborescence.
Les étapes futures ne sont pas des liens. "Confirmation" est du texte dans le <li>, pas un lien. L'utilisateur n'a pas encore atteint cette étape. Lui proposer un lien serait mensonger. Les étapes passées sont cliquables (tu peux y revenir), l'étape courante est identifiée, les étapes futures sont du texte brut.
Pas de schema.org. Le stepper est un composant d'interface, pas une donnée structurée. Google ne l'affiche pas dans les SERP. Et c'est normal, un tunnel de commande n'a pas vocation à être indexé.
Pour les séparateurs, même technique que le breadcrumb : CSS pur, ::before avec texte alternatif vide, zéro bruit pour les lecteurs d'écran.
Pour la logique métier des formulaires multi-étapes : validation, récapitulatif, gestion d'erreurs, voir Le laissez-passer A38, partie 3.
Les erreurs classiques du stepper
Le stepper est le composant le plus maltraité du web. Là où le breadcrumb est parfois absent, le stepper est souvent présent mais vide de sens.
La soupe de divLa majorité des steppers dans la nature ressemblent à ça : une rangée de <div> avec des classes .step-active, .step-completed, .step-disabled. Visuellement, ça fonctionne. Des cercles, des couleurs, des coches. Sémantiquement, c'est un néant. Un lecteur d'écran annonce une succession de textes sans aucune structure : pas de liste, pas d'ordre, pas de navigation. L'utilisateur ne sait pas combien d'étapes il reste, ni laquelle est la courante.
Même avec un <ol> correct, sans aria-current="step", l'étape courante n'est marquée que par la couleur. Un cercle bleu au lieu de gris. Pour quelqu'un qui ne voit pas les couleurs, ou qui ne voit pas du tout, chaque étape se ressemble.
Breadcrumb ou stepper ?
Deux questions suffisent.
Ta structure est un arbre ou une ligne ?Un catalogue, une documentation, un intranet : c'est un arbre. L'utilisateur navigue dans une hiérarchie et peut sauter à n'importe quel niveau. → Fil d'Ariane.
Un tunnel de commande, un formulaire d'inscription, un assistant : c'est une ligne. L'utilisateur avance étape par étape dans un ordre imposé. → Stepper.
L'utilisateur peut-il atteindre n'importe quel point ?Dans un fil d'Ariane, oui. Chaque niveau est un lien, toujours. Dans un stepper, non. Seules les étapes déjà complétées sont cliquables. Les étapes futures sont verrouillées.
Si tu hésites encore, pose-toi cette dernière question : est-ce que l'utilisateur explore ou est-ce qu'il progresse ? L'explorateur a besoin d'un fil d'Ariane. Le voyageur a besoin d'un stepper.
Les critères d'ensemble
Le fil d'Ariane répond à plusieurs critères du RGAA :
- Critère 12.1 — Chaque ensemble de pages doit proposer au moins deux systèmes de navigation différents parmi les trois admis par la note technique : menu de navigation, plan du site, moteur de recherche. Le fil d'Ariane n'en fait pas partie : il complète ces systèmes, il ne les remplace pas.
- Critère 12.2 — Le menu et les barres de navigation doivent être toujours à la même place. Le fil d'Ariane n'échappe pas à cette règle — il doit apparaître au même endroit sur chaque page.
Les WCAG encadrent aussi le fil d'Ariane :
- 2.4.5 Multiple Ways (AA) — Proposer plus d'un moyen de localiser une page dans un ensemble. Nuance importante : le fil d'Ariane n'est qu'une technique advisory (G65) pour ce critère, pas une technique suffisante, car il ne donne accès qu'aux pages ancêtres. Pour se situer, c'est le 2.4.8 ci-dessous qu'il sert vraiment.
- 2.4.8 Location (AAA) — L'utilisateur doit pouvoir savoir où il se trouve dans le site. Critère AAA, absent du RGAA, mais le fil d'Ariane y répond de façon exemplaire.
- 3.2.3 Consistent Navigation (AA) — Les mécanismes de navigation répétés sur plusieurs pages doivent apparaître dans le même ordre relatif.
- 4.1.2 Name, Role, Value (A) — Chaque composant a un nom accessible et un rôle.
<nav>fournit le rôle,aria-labelle nom,aria-currentl'état.