Podstawowe informacje o tym, jak utworzyć elastyczny i dostępny komponent ścieżki, który ułatwi użytkownikom poruszanie się po Twojej witrynie.
W tym poście chcę podzielić się przemyśleniami na temat tworzenia komponentów ścieżki. Wypróbuj wersję demonstracyjną
Jeśli wolisz film, obejrzyj tę wersję posta w YouTube:
Przegląd
Komponent ścieżki pokazuje, w którym miejscu hierarchii witryny znajduje się użytkownik. Nazwa pochodzi od Jasia i Małgosi, którzy w ciemnym lesie zostawiali za sobą okruszki chleba, aby móc wrócić do domu, śledząc je w odwrotnym kierunku.
Ścieżka w tym poście nie jest standardową ścieżką, tylko czymś podobnym. Oferują one dodatkowe funkcje, umieszczając strony pokrewne bezpośrednio w menu nawigacyjnym za pomocą ikony <select>, co umożliwia dostęp wielopoziomowy.
UX w tle
W filmie demonstracyjnym komponentu powyżej kategorie zastępcze to gatunki gier wideo. Ścieżka ta jest tworzona przez przejście do home »
rpg » indie » on sale, jak pokazano poniżej.
Ten komponent powinien umożliwiać użytkownikom poruszanie się po tej hierarchii informacji, szybkie i dokładne przechodzenie między gałęziami i wybieranie stron.
Architektura informacji
Warto myśleć w kategoriach kolekcji i elementów.
Kolekcje
Kolekcja to tablica opcji do wyboru. Na stronie głównej prototypu tego posta kolekcje to FPS, RPG, bijatyka, dungeon crawler, sport i puzzle.
Elementy
Gra wideo jest produktem, ale konkretna kolekcja również może być produktem, jeśli reprezentuje inną kolekcję. Na przykład RPG to produkt i prawidłowa kolekcja. Jeśli jest to produkt, użytkownik znajduje się na stronie kolekcji. Na przykład na stronie RPG, na której wyświetlana jest lista gier RPG, w tym dodatkowe podkategorie AAA, Indie i Self Published.
W terminologii informatycznej ten komponent ścieżki reprezentuje wielowymiarową tablicę:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
Twoja aplikacja lub witryna będzie mieć niestandardową architekturę informacji, która utworzy inny wielowymiarowy układ, ale mam nadzieję, że koncepcja stron docelowych kolekcji i przechodzenia po hierarchii znajdzie się również w Twoich ścieżkach.
Układy
Znacznik
Dobre komponenty zaczynają się od odpowiedniego kodu HTML. W następnej sekcji omówię moje wybory dotyczące znaczników i ich wpływ na cały komponent.
Ciemny i jasny schemat
<meta name="color-scheme" content="dark light">
Metatag color-scheme w powyższym fragmencie kodu informuje przeglądarkę, że ta strona chce korzystać ze stylów przeglądarki w wersji jasnej i ciemnej. Przykładowe ścieżki nie zawierają żadnych stylów CSS dla tych schematów kolorów, więc będą używać domyślnych kolorów udostępnianych przez przeglądarkę.
Element nawigacji
<nav class="breadcrumbs" role="navigation"></nav>
Do nawigacji w witrynie warto używać elementu <nav>, który ma domyślną rolę ARIA navigation.
Podczas testów zauważyłem, że atrybut role zmienił sposób, w jaki czytnik ekranu wchodził w interakcję z elementem. Był on odczytywany jako element nawigacyjny, dlatego zdecydowałem się go dodać.
Ikony
Jeśli ikona jest powtarzana na stronie, element SVG<use> oznacza, że możesz zdefiniować path raz i używać go we wszystkich wystąpieniach ikony. Zapobiega to powtarzaniu się tych samych informacji o ścieżce, co powoduje powiększanie się dokumentów i może prowadzić do niespójności ścieżek.
Aby użyć tej techniki, dodaj do strony ukryty element SVG i otocz ikony elementem <symbol> z unikalnym identyfikatorem:
<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>
Przeglądarka odczytuje kod HTML SVG, zapisuje informacje o ikonie w pamięci i przetwarza resztę strony, odwołując się do identyfikatora w przypadku dodatkowych zastosowań ikony, np. w ten sposób:
<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>

Zdefiniuj raz, używaj dowolną liczbę razy, przy minimalnym wpływie na wydajność strony i elastycznym stylu. Do elementu SVG dodano powiadomienie aria-hidden="true".
Ikony nie są przydatne dla osób, które przeglądają treści i tylko je słyszą. Ukrycie ich przed tymi użytkownikami zapobiega dodawaniu niepotrzebnego szumu.
Split-link .crumb
W tym miejscu tradycyjne ścieżki i ścieżki w tym komponencie różnią się od siebie.
Zwykle byłby to tylko <a> link, ale dodałem UX przechodzenia z ukrytym elementem select. Klasa .crumb odpowiada za układ linku i ikony, a klasa .crumbicon – za ułożenie ikony i elementu select w stos. Nazwałem go linkiem dzielonym, ponieważ jego funkcje są bardzo podobne do przycisku dzielonego, ale służy do nawigacji po stronie.
<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>
Link i kilka opcji to nic specjalnego, ale dodają więcej funkcji do prostych ścieżek. Dodanie atrybutu title do elementu <select> jest przydatne dla użytkowników czytników ekranu, ponieważ dostarcza im informacji o działaniu przycisku. Jednak ta funkcja jest przydatna dla wszystkich użytkowników. Na iPadzie jest ona widoczna na pierwszym planie. Jeden atrybut zapewnia kontekst przycisku wielu użytkownikom.

Dekoracje separatorów
<span class="crumb-separator" aria-hidden="true">→</span>
Separator jest opcjonalny. Wystarczy dodać tylko jeden (zobacz trzeci przykład w filmie powyżej). Następnie przypisuję każdemu z nich atrybut aria-hidden="true", ponieważ są to elementy dekoracyjne, których czytnik ekranu nie musi odczytywać.
Właściwość gap, o której piszemy dalej, ułatwia określanie odstępów.
Style
Ponieważ kolor korzysta z kolorów systemowych, w przypadku stylów są to głównie odstępy i stosy.
Kierunek i przepływ układu

Główny element nawigacyjny nav.breadcrumbs ustawia zakresową właściwość niestandardową, z której mogą korzystać elementy podrzędne, a poza tym tworzy układ poziomy wyrównany w pionie. Dzięki temu okruszki, separatory i ikony będą wyrównane.
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}

Każdy element .crumb tworzy też układ poziomy wyrównany pionowo z pewną przerwą, ale jest specjalnie przeznaczony dla elementów podrzędnych linku i określa styl white-space: nowrap. Jest to kluczowe w przypadku wielowyrazowych ścieżek, ponieważ nie chcemy, aby były one wielowierszowe. W dalszej części tego posta dodamy style, które pozwolą poradzić sobie z przepełnieniem w poziomie spowodowanym przez tę właściwość 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" jest dodawany, aby wyróżnić link do bieżącej strony. Użytkownicy czytników ekranu będą mieli wyraźny wskaźnik, że link dotyczy bieżącej strony. Dodatkowo wizualnie stylizujemy element, aby użytkownicy widzący mogli korzystać z podobnych funkcji.
Komponent .crumbicon używa siatki do ułożenia ikony SVG z „prawie niewidocznym” elementem <select>.

.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
Element <select> jest ostatnim elementem w DOM, więc znajduje się na górze stosu i jest interaktywny. Dodaj styl opacity: .01, aby element nadal był użyteczny, a wynikiem było pole wyboru idealnie dopasowane do kształtu ikony.
To dobry sposób na dostosowanie wyglądu elementu <select> przy zachowaniu wbudowanej funkcjonalności.
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
Przepełnienie
Ścieżka powinna być w stanie reprezentować bardzo długą ścieżkę. Lubię, gdy w odpowiednich przypadkach elementy mogą wykraczać poza ekran w poziomie, i uważam, że ten komponent ścieżki dobrze się do tego nadaje.
.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;
}}
}
Style przepełnienia zapewniają te funkcje:
- Przewijanie w poziomie z ograniczeniem przewijania.
- Dopełnienie przewijania w poziomie.
- Jeden punkt przyciągania na ostatnim okruszku. Oznacza to, że po wczytaniu strony pierwszy element ścieżki jest wczytywany w widocznym miejscu.
- Usuwa punkt przyciągania z Safari, która ma problemy z połączeniem przewijania w poziomie i efektu przyciągania.
Zapytania o multimedia
Jedną z subtelnych zmian w przypadku mniejszych obszarów wyświetlania jest ukrycie etykiety „Strona główna” i pozostawienie tylko ikony:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}

Ułatwienia dostępu
Ruch
W tym komponencie nie ma zbyt wiele ruchu, ale umieszczając przejście w instrukcji prefers-reduced-motion, możemy zapobiec niepożądanemu ruchowi.
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
Żaden z pozostałych stylów nie wymaga zmiany. Efekty najechania kursorem i skupienia są świetne i znaczące bez transition, ale jeśli ruch jest dopuszczalny, dodamy subtelną animację przejścia do interakcji.
JavaScript
Po pierwsze, niezależnie od typu routera używanego w witrynie lub aplikacji, gdy użytkownik zmieni ścieżkę, adres URL musi zostać zaktualizowany, a użytkownikowi musi się wyświetlić odpowiednia strona. Po drugie, aby ujednolicić wrażenia użytkowników, zadbaj o to, aby podczas przeglądania <select>opcji nie dochodziło do nieoczekiwanych nawigacji.
Dwa kluczowe wskaźniki UX obsługiwane przez JavaScript: select has
changed i zapobieganie wywoływaniu zdarzenia zmiany <select>.
Zapobieganie przedwczesnym zdarzeniom jest konieczne ze względu na użycie elementu <select>. W przeglądarce Edge w systemie Windows (i prawdopodobnie w innych przeglądarkach) zdarzenie changed
jest wywoływane, gdy użytkownik przegląda opcje za pomocą klawiatury. Dlatego nazwałem to „szybkim wyborem”, ponieważ użytkownik tylko pozornie wybrał opcję, np. przez najechaniu na nią kursorem lub ustawieniu na niej fokusu, ale nie potwierdził wyboru za pomocą enter ani click. Zdarzenie eager uniemożliwia korzystanie z tej funkcji zmiany kategorii komponentu, ponieważ otwarcie pola wyboru i przeglądanie elementu spowoduje wywołanie zdarzenia i zmianę strony, zanim użytkownik będzie na to gotowy.
Ulepszone <select> zmienione wydarzenie
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
})
})
Strategia polega na obserwowaniu zdarzeń naciśnięcia klawisza na każdym elemencie <select> i określaniu, czy naciśnięty klawisz służył do potwierdzenia nawigacji (Tab lub Enter), czy do nawigacji przestrzennej (ArrowUp lub ArrowDown). Na podstawie tego określenia komponent może zdecydować, czy ma czekać, czy przejść dalej, gdy zostanie wywołane zdarzenie elementu <select>.
Podsumowanie
Teraz, gdy wiesz, jak to zrobiłem, jak Ty byś to zrobił? 🙂
Urozmaićmy nasze podejście i poznajmy wszystkie sposoby tworzenia treści w internecie. Utwórz demo, wyślij mi na Twitterze linki, a ja dodam je do sekcji remiksów społeczności poniżej.
Remiksy społeczności
- Tux Solbakk jako komponent internetowy: wersja demonstracyjna i kod