Breadcrumb
Hierarchical navigation showing the user's location in a site or app.
Uses <nav> + <ol> for semantic correctness. Separator is a
chevron (›) drawn via CSS, so it does not appear in the
accessibility tree.
When to use
- Multi-level navigation where users benefit from knowing where they are and how to step back up.
- Documentation, e-commerce category pages, admin tools.
If the hierarchy has only one level deep ("Home > Page"), prefer a back link or no breadcrumb at all.
Variants
| Variant | Class | Use for |
|---|---|---|
| Default | .breadcrumb |
Standard, subtle ink |
| Strong | .breadcrumb.-strong |
Higher-contrast, accent current page |
Anatomy
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol class="breadcrumb__list">
<li class="breadcrumb__item">
<a class="breadcrumb__link" href="/">Home</a>
</li>
<li class="breadcrumb__item">
<a class="breadcrumb__link" href="/docs">Documentation</a>
</li>
<li class="breadcrumb__item" aria-current="page">Components</li>
</ol>
</nav>
The current page is a plain <li> (not a link) with
aria-current="page". Authors should NOT make the current page a
link — it would navigate to itself.
Separator
A chevron (›) renders before every item except the first via CSS
::before. The character is selected for clarity and is the
agreed v1.0 default (see the design decision recorded with this
component).
The separator is decorative — being a pseudo-element, it does not appear in the accessibility tree. Screen readers read the list as a sequence of links + the current page.
Tokens used
From semantic tier
--color-ink-strong— current page text, link hover--color-ink-regular— link default--color-ink-subtle— separator, default ambient text--color-accent— strong-variant current page, focus ring--space-gap-elements-s— gap between items--space-inset-element-s— link padding--radius-tag— link focus radius--border-width-focus/--border-width-hairline--font-body-support-*— typography--motion-fast/--motion-easing-default— link hover transition
Accessibility
- The outer element is
<nav aria-label="Breadcrumb">. Screen readers announce it as a navigation landmark. - The list is
<ol>(ordered, since position carries meaning). - The current page uses
aria-current="page". Assistive tech reads it as "current page". - The chevron separator is a CSS pseudo-element, not in the DOM, so it
is excluded from the accessibility tree without needing
aria-hidden. - Links are real
<a>elements — full keyboard support, focus ring, context menus.
Edge cases
- Long trails: breadcrumbs wrap onto multiple lines via
flex-wrap: wrap. For very deep hierarchies, consider truncating middle items with an ellipsis link that exposes the full trail on click (v1.1 enhancement; not in v1.0 base). - Mobile: the standard layout works down to ~360px. For very cramped UIs, consider using only the parent + current label.
- Internationalization: the chevron
›renders identically in RTL scripts as a visual element. Authors with strict LTR/RTL conventions may override thecontentvalue via a custom class.
Do
- Always wrap in
<nav aria-label="Breadcrumb">. - Use
<ol>not<ul>— order matters. - Mark the current page with
aria-current="page"and render as text, not a link. - Keep labels short — the goal is recognition, not exposition.
Don't
- Don't make the current page a link.
- Don't include the chevron in the DOM. Let CSS handle it so the accessibility tree stays clean.
- Don't use breadcrumbs as the primary navigation. They are a secondary "you are here" aid.