Découvrez comment créer un composant de fil d'Ariane réactif et accessible pour que les utilisateurs puissent parcourir votre site.
Dans cet article, je vais vous présenter une façon de créer des composants de fil d'Ariane. Tester la fonctionnalité
Si vous préférez la vidéo, voici une version YouTube de cet article:
Présentation
Un composant fil d'Ariane indique l'emplacement de l'utilisateur dans la hiérarchie du site. Ce nom vient d'Hansel et Gretel, qui ont laissé des miettes de pain derrière eux dans une forêt sombre et ont pu retrouver leur chemin en suivant les miettes en arrière.
Les éléments de navigation de cet article ne sont pas des éléments de navigation standards, mais des éléments de navigation similaires. Elles offrent des fonctionnalités supplémentaires en plaçant
directement dans la navigation à l'aide d'un <select>
, ce qui rend l'accès à plusieurs niveaux
possible.
Expérience utilisateur en arrière-plan
Dans la vidéo de démonstration du composant ci-dessus, les catégories d'espace réservé sont des genres
des jeux vidéo. Pour créer ce chemin, accédez à home »
rpg » indie » on sale
, comme illustré ci-dessous.
Ce composant de fil d'Ariane doit permettre aux utilisateurs de parcourir cette hiérarchie d'informations, en sautant des branches et en sélectionnant des pages rapidement et précisément.
Architecture de l’information
Je trouve utile de penser en termes de collections et d'éléments.
Collections
Une collection est un tableau d'options parmi lesquelles choisir. Sur la page d'accueil de le prototype de fil d'Ariane de cet article, les collections sont les jeux de tirs, les jeux de rôle, les brawlers, le robot d'exploration de donjons, les sports et les puzzles.
Éléments
Un jeu vidéo est un élément. Une collection spécifique peut également être un élément si elle représente une autre collection. Par exemple, "RPG" est un élément et une collection valide. S'il s'agit d'un article, l'utilisateur se trouve sur la page de cette collection. Par exemple, elles se trouvent sur la page des jeux de rôle, qui affiche une liste de jeux de rôle, y compris les sous-catégories supplémentaires AAA, indépendants et auto-publiés.
En informatique, ce composant de fil d'Ariane représente multidimensionnelle tableau:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
Votre application ou votre site Web aura une architecture de l'information (AI) personnalisée qui créera un tableau multidimensionnel différent, mais j'espère que le concept de pages de destination de collection et de parcours hiérarchique pourra également être intégré à vos miettes de pain.
Mises en page
Majoration
Un bon composant commence par le code HTML approprié. Dans la prochaine section, vos choix de balisage et leur impact sur l'ensemble du composant.
Thème sombre et clair
<meta name="color-scheme" content="dark light">
La balise méta color-scheme
de l'extrait ci-dessus informe le navigateur que cette page souhaite les styles de navigateur clair et sombre. Les exemples de fil d'Ariane n'incluent aucun CSS pour ces jeux de couleurs. Ils utiliseront donc les couleurs par défaut fournies par le navigateur.
Élément de navigation
<nav class="breadcrumbs" role="navigation"></nav>
Il est approprié d'utiliser l'élément <nav>
pour la navigation sur le site, qui a un rôle ARIA implicite de navigation.
Lors des tests, j'ai remarqué que l'attribut role
avait changé la façon dont
le lecteur d'écran interagissait avec l'élément, celui-ci a en fait été annoncé comme
navigation, et j'ai donc choisi de l'ajouter.
Icônes
Lorsqu'une icône est répétée sur une page, l'élément SVG <use>
vous permet de définir path
une fois et de l'utiliser pour toutes les instances de l'icône. Cela évite que les mêmes informations
de chemin soient répétées, ce qui entraîne
des documents plus volumineux et le risque
d'incohérence dans les chemins.
Pour utiliser cette technique, ajoutez un élément SVG masqué à la page et encapsulez les icônes.
dans un élément <symbol>
avec un identifiant unique:
<svg style="display: none;">
<symbol id="icon-home">
<title>A home icon</title>
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</symbol>
<symbol id="icon-dropdown-arrow">
<title>A down arrow</title>
<path d="M19 9l-7 7-7-7"/>
</symbol>
</svg>
Le navigateur lit le code HTML SVG, met les informations de l'icône en mémoire et poursuit le reste de la page en référençant l'ID pour d'autres utilisations de l'icône, comme suit :
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-home" />
</svg>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-dropdown-arrow" />
</svg>
Définissez une fois, utilisez autant de fois que vous le souhaitez, avec un impact minimal sur les performances de la page et un style flexible. Notez que aria-hidden="true"
a été ajouté à l'élément SVG.
Les icônes ne sont pas utiles à un utilisateur qui ne voit que le contenu audio. En les masquant, vous évitez qu'il ajoute du bruit inutile.
Lien fractionné .crumb
C'est là que le fil d'Ariane traditionnel et ceux de ce composant divergent.
Normalement, il ne s'agirait que d'un lien <a>
, mais j'ai ajouté l'expérience utilisateur de balayage
une sélection déguisée. La classe .crumb
est responsable de la mise en page du lien.
l'icône, tandis que .crumbicon
se charge d'empiler l'icône et de sélectionner
ensemble. Je l'ai appelé "split-link", car ses fonctions sont très
semblable à un split-button,
mais pour la navigation sur les pages.
<span class="crumb">
<a href="#sub-collection-b">Category B</a>
<span class="crumbicon">
<svg>...</svg>
<select class="disguised-select" title="Navigate to another category">
<option>Category A</option>
<option selected>Category B</option>
<option>Category C</option>
</select>
</span>
</span>
Un lien et certaines options n'ont rien de spécial, mais ils ajoutent des fonctionnalités à une
fil d'Ariane simple. Ajouter un title
à l'élément <select>
est utile pour les utilisateurs de lecteurs d'écran, car il leur fournit des informations sur l'action du bouton. Cependant, il
offre la même aide à tous les autres
également, vous verrez qu'il est au premier plan
iPad. Un seul attribut fournit le contexte du bouton à de nombreux utilisateurs.
Décorations de séparateurs
<span class="crumb-separator" aria-hidden="true">→</span>
Il n'est pas obligatoire d'en ajouter un, mais vous pouvez aussi en ajouter un (voir le troisième exemple dans la vidéo).
ci-dessus). Je donne ensuite chaque aria-hidden="true"
, car il est décoratif et non
quelque chose qu'un lecteur
d'écran doit annoncer.
La propriété gap
, qui sera abordée plus loin, permet de définir facilement l'espacement de ces éléments.
Styles
Étant donné que la couleur utilise des couleurs système, les styles sont principalement constitués d'espaces et de piles.
Sens et flux de la mise en page
L'élément de navigation principal nav.breadcrumbs
définit une propriété personnalisée délimitée.
adaptée aux enfants, ou si elle est alignée verticalement
mise en page. Cela garantit que les miettes, les séparateurs et les icônes sont alignés.
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}
Chaque .crumb
établit également une mise en page horizontale alignée verticalement avec un espacement, mais cible spécifiquement ses enfants de lien et spécifie le style white-space: nowrap
. C'est crucial pour les fils d'Ariane de plusieurs mots, car nous ne
pour qu'ils soient multilignes. Plus loin dans cet article, nous ajouterons des styles pour gérer le débordement horizontal causé par cette propriété white-space
.
.crumb {
display: inline-flex;
align-items: center;
gap: calc(var(--nav-gap) / 4);
& > a {
white-space: nowrap;
&[aria-current="page"] {
font-weight: bold;
}
}
}
aria-current="page"
est ajouté pour que le lien de la page actuelle se démarque des autres. Les utilisateurs de lecteurs d'écran disposent d'un indicateur clair indiquant que le lien concerne la page actuelle. Nous avons également stylisé l'élément visuellement pour aider les utilisateurs voyants à bénéficier d'une expérience utilisateur similaire.
Le composant .crumbicon
utilise une grille pour empiler une icône SVG avec une ligne "presque
invisible" Élément <select>
.
.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
L'élément <select>
est le dernier du DOM. Il se trouve donc au sommet de la pile et est interactif. Ajoutez un style opacity: .01
pour que l'élément soit toujours utilisable.
et le résultat est une zone de sélection
qui s'adapte parfaitement à la forme de l'icône.
C'est un bon moyen de personnaliser l'apparence d'un élément <select>
tout en conservant la fonctionnalité intégrée.
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
Dépassement
Un fil d'Ariane doit pouvoir représenter une très longue piste. Je suis fan de permettre les choses sortent de l'écran horizontalement, le cas échéant, et je sentais que le composant "fil d'Ariane" est bien qualifié.
.breadcrumbs {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x proximity;
scroll-padding-inline: calc(var(--nav-gap) / 2);
& > .crumb:last-of-type {
scroll-snap-align: end;
}
@supports (-webkit-hyphens:none) { & {
scroll-snap-type: none;
}}
}
Les styles de débordement configurent l'expérience utilisateur suivante:
- Défilement horizontal avec défilement hors limites.
- Marge intérieure de défilement horizontal.
- Un point d'ancrage sur la dernière miette. Ainsi, lors du chargement de la page, des miettes chargées dans le champ de vision.
- Supprime le point d'ancrage de Safari, qui a du mal avec le format horizontal le défilement et les combinaisons d'effets d'ancrage.
Requêtes média
Pour les fenêtres d'affichage de petite taille, il suffit de masquer la page d'accueil libellé, laissant uniquement l'icône:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}
Accessibilité
Mouvement
Il n'y a pas beaucoup de mouvement dans ce composant, mais en encapsulant la transition dans une vérification prefers-reduced-motion
, nous pouvons éviter les mouvements indésirables.
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
Aucun autre style n'a besoin de changer, les effets de survol et de focus sont excellents
et pertinent sans transition
, mais si le mouvement convient, nous ajoutons une subtilité
à l'interaction.
JavaScript
Tout d'abord, quel que soit le type de routeur que vous utilisez sur votre site ou dans votre application, lorsqu'un utilisateur modifie les miettes de pain, l'URL doit être mise à jour et la page appropriée doit s'afficher. Deuxièmement, pour normaliser
l'expérience utilisateur, assurez-vous
Aucune navigation inattendue ne se produit lorsque les utilisateurs parcourent simplement <select>
options.
Deux mesures critiques concernant l'expérience utilisateur doivent être gérées par JavaScript: select a
modification et préconisation du déclenchement d'événements de modification de <select>
.
La prévention des événements extrêmes est nécessaire en raison de l'utilisation d'un <select>
.
. Dans Windows Edge et probablement dans d'autres navigateurs, l'événement de sélection changed
se déclenche lorsque l'utilisateur parcourt les options avec le clavier. C'est pourquoi je
comme "eager", car l'utilisateur n'a que pseudo-sélectionné l'option, comme un survol
ou le focus, mais n'a pas encore confirmé le choix avec enter
ou click
. L'événement impatient rend cette fonctionnalité de modification de catégorie de composant inaccessible, car l'ouverture de la zone de sélection et la simple navigation sur un élément déclenchent l'événement et modifient la page avant que l'utilisateur ne soit prêt.
Amélioration de l'événement "<select>
" modifié
const crumbs = document.querySelectorAll('.breadcrumbs select')
const allowedKeys = new Set(['Tab', 'Enter', ' '])
const preventedKeys = new Set(['ArrowUp', 'ArrowDown'])
// watch crumbs for changes,
// ensures it's a full value change, not a user exploring options via keyboard
crumbs.forEach(nav => {
let ignoreChange = false
nav.addEventListener('change', e => {
if (ignoreChange) return
// it's actually changed!
})
nav.addEventListener('keydown', ({ key }) => {
if (preventedKeys.has(key))
ignoreChange = true
else if (allowedKeys.has(key))
ignoreChange = false
})
})
La stratégie consiste à surveiller les événements de pression du clavier sur chaque <select>
.
et déterminer si la touche utilisée correspond à une confirmation de navigation (Tab
ou
Enter
) ou la navigation spatiale (ArrowUp
ou ArrowDown
). Grâce à cette
le composant peut décider d'attendre ou de partir, lorsque l'événement
L'élément <select>
se déclenche.
Conclusion
Maintenant que vous savez comment j'ai fait, comment procéderiez-vous ? 🙂
Diversifions nos approches et découvrons toutes les façons de créer sur le Web. Créez une démo, tweetez-moi des liens et je l'ajouterai à la section "Remix de la communauté" ci-dessous.
Remix de la communauté
- Tux Solbakk en tant que composant Web: démonstration et code