Una panoramica di base su come creare un componente di breadcrumb reattivo e accessibile per consentire agli utenti di navigare sul tuo sito.
In questo post voglio parlare di un modo per creare componenti dei breadcrumb. Prova la demo.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
Un componente breadcrumb mostra in che punto della gerarchia del sito si trova l'utente. Il nome è Hansel e Gretel, che ha abbandonato nel bosco scuro e sono riuscito a trovare la strada di casa tracciando le briciole all'indietro.
I breadcrumb in questo post non sono standard
breadcrumb,
sono simili ai breadcrumb. Offrono funzionalità aggiuntive inserendo
pagine direttamente nella navigazione con un <select>
, rendendo l'accesso a più livelli
possibile.
UX in background
Nel video dimostrativo sui componenti riportato sopra, le categorie segnaposto sono generi di
videogiochi. Questo sentiero viene creato seguendo il seguente percorso: home »
rpg » indie » on sale
, come mostrato di seguito.
Questo componente breadcrumb deve consentire agli utenti di spostarsi la gerarchia delle informazioni; saltando rami e selezionando pagine velocemente e la precisione.
Architettura dell'informazione
Penso che sia utile pensare in termini di raccolte ed elementi.
Raccolte
Una raccolta è un insieme di opzioni tra cui scegliere. Dalla home page di il prototipo di breadcrumb del post, le raccolte sono FPS, RPG, brawler, dungeon crawler, sport e rompicapi.
Elementi
Un videogioco è un elemento, anche una raccolta specifica potrebbe essere un elemento rappresenta un'altra raccolta. Ad esempio, RPG è un elemento e un modello . Se si tratta di un elemento, l'utente si trova nella pagina della raccolta. Ad esempio: nella pagina RPG, che mostra un elenco di giochi RPG, tra cui ulteriori sottocategorie "AAA", "Indie" e "Autopubblicati".
In termini informatici, questo componente dei breadcrumb rappresenta un multidimensionale di testo:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
La tua app o il tuo sito web avranno un'architettura delle informazioni personalizzata (IA), creando un un array multidimensionale diverso, ma spero che il concetto di atterraggio della collezione pagine e l'attraversamento gerarchia possono comparire anche nei breadcrumb.
Layout
Aumento
I componenti efficaci iniziano con un codice HTML appropriato. Nella prossima sezione illustrerò scelte di markup e come influiscono sul componente complessivo.
Schema scuro e chiaro
<meta name="color-scheme" content="dark light">
Il meta tag color-scheme
in alto
Lo snippet comunica al browser che questa pagina richiede il browser chiaro e scuro.
stili. I breadcrumb di esempio non includono CSS per queste combinazioni di colori,
quindi i breadcrumb utilizzeranno i colori predefiniti forniti dal browser.
Elemento di navigazione
<nav class="breadcrumbs" role="navigation"></nav>
È opportuno utilizzare
Elemento <nav>
per la navigazione sul sito, che ha un ruolo ARIA implicito
navigazione.
Durante i test, ho notato che con l'attributo role
il modo in cui un
screen reader ha interagito con l'elemento, in realtà è stato annunciato
di navigazione, quindi ho scelto di aggiungerla.
Icone
Quando un'icona si ripete su una pagina, il file SVG
Elemento <use>
significa che puoi definire path
una volta e utilizzarlo per tutte le istanze
. In questo modo le informazioni sul percorso non vengono ripetute, causando
documenti più grandi e la potenziale
incoerenza del percorso.
Per utilizzare questa tecnica, aggiungi un elemento SVG nascosto alla pagina e aggrega le icone
in un elemento <symbol>
con un ID univoco:
<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>
Il browser legge l'HTML SVG, inserisce in memoria le informazioni sull'icona e continua con il resto della pagina facendo riferimento all'ID per ulteriori utilizzi dell'icona, in questo modo:
<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>
Definite una volta e utilizzate tutte le volte che volete, con un impatto minimo sulle prestazioni della pagina.
e stili flessibili. Nota che aria-hidden="true"
viene aggiunto all'elemento SVG.
Le icone non sono utili a chi naviga e ascolta solo i contenuti, nascondendo
per impedire l'aggiunta di rumore superfluo.
Link di suddivisione .crumb
È qui che divergono il breadcrumb tradizionale e quelli in questo componente.
Normalmente, si tratta di un solo link <a>
, ma ho aggiunto un'esperienza utente trasversale con un
selezione camuffata. Il corso .crumb
si occupa della disposizione del link e
l'icona, mentre .crumbicon
si occupa della sovrapposizione dell'icona e selezionare
insieme. L'ho definito link divisi perché le sue funzioni sono molto
simile a split-button,
ma per la navigazione nelle pagine.
<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 link e alcune opzioni non sono speciali, ma aggiungono più funzionalità a un
breadcrumb semplice. L'aggiunta di title
all'elemento <select>
è utile per lo schermo
agli utenti lettori, fornendo loro informazioni sull'azione del pulsante. Comunque
offre lo stesso aiuto anche a tutti gli altri, vedrai che è in primo piano
iPad. Un attributo fornisce il contesto del pulsante a molti utenti.
Decorazioni separatore
<span class="crumb-separator" aria-hidden="true">→</span>
I separatori sono facoltativi; anche l'aggiunta di un solo separatore funziona molto bene (guarda il terzo esempio del video
sopra). Poi do a ogni aria-hidden="true"
perché sono decorativi e non
qualcosa che uno screen reader deve annunciare.
La proprietà gap
, trattata di seguito, semplifica la spaziatura di questi elementi.
Stili
Poiché il colore utilizza i colori del sistema, si tratta principalmente di spazi vuoti e impilati per gli stili.
Direzione e flusso del layout
L'elemento di navigazione principale nav.breadcrumbs
imposta una proprietà personalizzata con ambito
che i bambini possono usare e stabilisce in altro modo una
layout. In questo modo le briciole, i divisori e le icone saranno allineati.
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}
Ogni .crumb
stabilisce anche un layout orizzontale allineato verticalmente con alcune
gap, ma ha come target in modo speciale gli elementi secondari dei link e specifica lo stile
white-space: nowrap
. Questo è fondamentale per i breadcrumb di più parole, perché
devono passare su più righe. Più avanti in questo post aggiungeremo gli stili per gestire
overflow orizzontale di questa proprietà white-space
causato.
.crumb {
display: inline-flex;
align-items: center;
gap: calc(var(--nav-gap) / 4);
& > a {
white-space: nowrap;
&[aria-current="page"] {
font-weight: bold;
}
}
}
Il link aria-current="page"
viene aggiunto per mettere in risalto il link della pagina corrente rispetto a
e riposare. Non solo gli utenti di screen reader avranno un chiaro indicatore del fatto che il link sia
per la pagina corrente, abbiamo applicato uno stile visivo all'elemento per aiutare gli utenti vedenti
offrire un'esperienza utente simile.
Il componente .crumbicon
utilizza una griglia per sovrapporre un'icona SVG all'icona "quasi
invisibile" Elemento <select>
.
.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
L'elemento <select>
è l'ultimo nel DOM, quindi si trova in cima allo stack,
e interattivo. Aggiungi lo stile opacity: .01
in modo che l'elemento sia ancora utilizzabile,
il risultato è una casella di selezione che si adatta perfettamente alla forma dell'icona.
Questo è un ottimo modo per personalizzare l'aspetto di un elemento <select>
, mentre
mantenendo la funzionalità integrata.
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
Overflow
I breadcrumb dovrebbero essere in grado di rappresentare una scia molto lunga. Adoro consentire fuori schermo in orizzontale, quando opportuno, e ho sentito dei breadcrumb correttamente.
.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;
}}
}
Gli stili extra configurano la seguente UX:
- Scorrimento orizzontale con contenimento overscroll.
- Spaziatura interna di scorrimento orizzontale.
- Un punto di scatto sull'ultima briciola. Ciò significa che al caricamento della pagina carichi di briciole agganciati e visibili.
- Rimuove il punto di aggancio da Safari, che ha difficoltà con l'orientamento orizzontale combinazioni di effetti di scorrimento e aggancio.
Query supporti
Una piccola modifica alle aree visibili più piccole è nascondere "Home" etichetta, lasciando solo l'icona:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}
Accessibilità
Movimento
Non c'è molto movimento in questo componente, ma racchiudendo la
transizione in un controllo prefers-reduced-motion
, possiamo impedire movimenti indesiderati.
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
Nessuno degli altri stili deve cambiare, gli effetti al passaggio del mouse e di messa a fuoco sono fantastici
e significativo senza transition
, ma se il movimento è accettabile, aggiungeremo un
transizione all'interazione.
JavaScript
Innanzitutto, a prescindere dal tipo di router utilizzato nel sito o nell'applicazione,
Quando un utente modifica i breadcrumb, l'URL deve essere aggiornato e l'utente
visualizzata la pagina appropriata. In secondo luogo, per normalizzare l'esperienza utente,
non si verificano navigazioni impreviste quando gli utenti navigano su <select>
le opzioni di CPU e memoria disponibili.
Due misure fondamentali per l'esperienza utente che devono essere gestite da JavaScript: select ha
prevenzione dell'attivazione di eventi di modifica <select>
modificata e desiderosa.
È necessaria la prevenzione di eventi "eager" grazie all'uso di un <select>
. Su Windows Edge e probabilmente anche in altri browser, changed
si attiva mentre l'utente sfoglia le opzioni con la tastiera. È per questo che
chiamato "eager", dato che l'utente ha solo pseudo selezionato l'opzione, come
o focus, ma non ha ancora confermato la scelta con enter
o click
. L'impazienza
rende inaccessibile la funzione di modifica della categoria del componente, perché
aprire la casella di selezione e semplicemente sfogliare un elemento attiverà l'evento e
modificare la pagina prima che l'utente sia pronto.
Un evento <select>
migliore modificato
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 strategia per farlo è controllare gli eventi Tastiera giù ogni <select>
e stabilire se il tasto premuto è la conferma della navigazione (Tab
o
Enter
) o navigazione spaziale (ArrowUp
o ArrowDown
). Con questo
determinante, il componente può decidere di attendere o di andare, quando l'evento per
Viene attivato <select>
elemento.
Conclusione
Ora che sai come ci ho fatto, come faresti‽ 🙂
Diversificaamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea una demo, twittami con i link e la aggiungerò alla sezione dei remix della community qui sotto.
Remix della community
- Tux Solbakk come componente web: demo e codice