Créer un composant de fil d'Ariane

Découvrez comment créer un composant "fil d'Ariane" réactif et accessible pour que les utilisateurs puissent parcourir votre site.

Dans ce message, je vais vous expliquer comment créer des composants de fil d'Ariane. Tester la fonctionnalité

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Démonstration

Si vous préférez la vidéo, voici une version YouTube de cet article:

Présentation

Un composant fil d'Ariane affiche où se trouve l'utilisateur dans la hiérarchie du site. Son nom vient de Hansel et Gretel, qui a abandonné passaient du fil d'Ariane derrière eux dans une forêt sombre et ont pu trouver le chemin du retour en traçant des miettes vers l'arrière.

Les fils d'Ariane de ce message ne sont pas standards fils d'Ariane, elles ressemblent à des fils d'Ariane. 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. Ce sentier a été créé en suivant le chemin suivant: home » rpg » indie » on sale, comme indiqué ci-dessous.

Ce composant de fil d'Ariane doit permettre aux utilisateurs la hiérarchie des informations ; sauter des branches et sélectionner des pages rapidement et précision.

Architecture de l’information

Il est utile de réfléchir 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 aussi être un élément si elle représente une autre collection. Par exemple, un RPG est un objet et collection. S'il s'agit d'un article, l'utilisateur se trouve sur la page de cette collection. Par exemple : il se trouve sur la page du jeu de rôle, qui affiche une liste de jeux de rôle, y compris les supplémentaires sous-catégories AAA, Indé et Auto-publication.

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 des informations (AI) personnalisée, ce qui créera une un tableau multidimensionnel différent, mais j'espère que le concept de collecte les pages et le balayage hiérarchique peuvent également figurer dans votre fil d'Ariane.

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 Meta color-scheme ci-dessus un extrait informe le navigateur que cette page souhaite que les navigateurs clairs et sombres . L'exemple de fil d'Ariane n'inclut aucun CSS pour ces jeux de couleurs, Le fil d'Ariane utilisera donc les couleurs par défaut fournies par le navigateur.

<nav class="breadcrumbs" role="navigation"></nav>

Il est approprié d'utiliser Élément <nav> pour la navigation sur le site, qui possède un rôle ARIA implicite 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'image SVG Élément <use> signifie que vous pouvez définir path une seule fois et l'utiliser pour toutes les instances de . Cela empêche la répétition des mêmes informations de chemin d'accès, 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, place les informations de l'icône en mémoire continue avec le reste de la page en référence à l'ID pour d'autres utilisations l'icône, comme ceci:

<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>

Outils de développement affichant un élément d&#39;utilisation SVG

Définissez cette règle une seule fois et utilisez-la autant de fois que vous le souhaitez, avec un impact minimal sur les performances des pages et un style flexible. Notez que aria-hidden="true" a été ajouté à l'élément SVG. Ces icônes ne sont pas utiles pour une personne qui parcourt le Web et qui n'entend que le contenu. de ces utilisateurs les empêche d’ajouter du bruit inutile.

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. L'ajout d'un title à l'élément <select> est utile pour l'écran les utilisateurs de lecteurs, ce qui leur donne des informations sur l'action du bouton. Toutefois, il offre la même aide à tous les autres également, vous verrez qu'il est au premier plan iPad. Un attribut fournit le contexte du bouton à de nombreux utilisateurs.

Capture d&#39;écran avec l&#39;élément de sélection invisible en train d&#39;être survolé et ses
info-bulle contextuelle affichée.

Décorations du séparateur

<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, abordée ci-après, permet de simplifier l'espacement entre ces éléments.

Styles

Étant donné que la couleur utilise des couleurs système, il s'agit principalement d'espaces et de piles de styles.

Sens et flux de la mise en page

Outils de développement montrant l&#39;alignement du fil d&#39;Ariane avec sa superposition Flexbox
.

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);
}

Un fil d&#39;Ariane affiché verticalement avec des superpositions Flexbox.

Chaque .crumb établit également une mise en page horizontale alignée verticalement avec certaines gap, mais cible spécifiquement ses liens enfants 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 dépassement horizontal de cette propriété white-space causé.

.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" a été ajouté pour aider le lien de la page actuelle à se démarquer de la reste. Non seulement les utilisateurs de lecteurs d'écran auront un indicateur clair que le lien est pour la page actuelle, nous avons appliqué un style visuel à l'élément afin d'aider les personnes voyantes d’obtenir 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>.

Outils pour les développeurs Grid affichés en superposition sur un bouton où la ligne et la colonne
une pile nommée.

.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> se trouve en dernier dans le DOM. Il se trouve donc au-dessus de la pile. et 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 en maintenant 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;
  }
}

côte à côte du fil d&#39;Ariane avec et sans libellé de maison, par
comparaison.

Accessibilité

Mouvement

Il n'y a pas beaucoup de mouvement dans ce composant, mais en encapsulant le lors d'une vérification prefers-reduced-motion, nous pouvons empêcher tout mouvement indésirable.

@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 le fil d'Ariane, l'URL doit être mise à jour et l'utilisateur la page appropriée s'affiche. 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>. . Sur Windows Edge, et probablement sur d'autres navigateurs, l'option changed se déclenche lorsque l'utilisateur parcourt les différentes options à l'aide du 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’impatient rend cette fonctionnalité de modification de catégorie de composant inaccessible, car ouvrir la boîte de sélection et parcourir un élément pour déclencher l'événement changer de 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 quitter la page, au moment où L'élément <select> se déclenche.

Conclusion

Maintenant que vous savez comment j'ai fait, comment feriez-vous ? 😃

Diversifiez nos approches et découvrons toutes les manières de créer des applications sur le Web. Créer une démonstration, me envoyer des tweets et je l'ajouterai à la section des remix de la communauté ci-dessous.

Remix de la communauté