defuss-shadcn / Navigation / breadcrumb
BreadcrumbATM
Displays the path to the current page. Built on <nav> + <ol>.
On this page (8)
§Default
Slash-separated navigation trail with links and a current page.
§Custom separator
Chevron icon separators instead of slashes.
§Collapsed
Long trails can collapse middle items into an ellipsis.
§With icons
Put an icon in front of any crumb - an svg (here lucide) as the first child of .breadcrumb-link / .breadcrumb-page. It is sized to the text (1em) and centered on the label.
§With emojis
An emoji goes in a .breadcrumb-icon span (aria-hidden - the label already names the crumb) so it keeps a square box and lines up like an icon.
§Icons scale with the size
Icons and emojis are 1em, so data-size grows them with the labels.
§Sizes
Set data-size on the .breadcrumb nav to scale the trail's type and separators together - the ladder mirrors the shared field sizes (md matches the unsized default).
§CSS view file
Styles for the breadcrumb component. Uses design tokens for colors, spacing, and radius.
@layer components { .breadcrumb-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; list-style: none; margin: 0; padding: 0; font-size: 0.875rem; } .breadcrumb-item { display: inline-flex; align-items: center; gap: 0.375rem; } .breadcrumb-link { color: var(--muted-foreground); text-decoration: none; border-radius: var(--radius-sm); outline: none; transition: color 150ms ease; &:hover { color: var(--foreground); } /* only a real link underlines - a .breadcrumb-link button (dropdown / ellipsis trigger) is not navigation and keeps the color-only hover */ &:is(a[href]):hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; } } /* -- Sizes ------------------------------------------------------ data-size on the .breadcrumb nav scales the trail's type and separators, mirroring the shared field/button ladder (md = 0.875rem = default). */ .breadcrumb[data-size="xs"] .breadcrumb-list { font-size: 0.75rem; } .breadcrumb[data-size="xs"] .breadcrumb-separator svg { width: 0.75rem; height: 0.75rem; } .breadcrumb[data-size="sm"] .breadcrumb-list { font-size: 0.8125rem; } .breadcrumb[data-size="md"] .breadcrumb-list { font-size: 0.875rem; } .breadcrumb[data-size="lg"] .breadcrumb-list { font-size: 1rem; } .breadcrumb[data-size="lg"] .breadcrumb-separator svg { width: 1rem; height: 1rem; } .breadcrumb[data-size="xl"] .breadcrumb-list { font-size: 1.125rem; } .breadcrumb[data-size="xl"] .breadcrumb-separator svg { width: 1.125rem; height: 1.125rem; } .breadcrumb-separator { color: var(--muted-foreground); font-size: 0.75rem; /* flex (not inline): an inline <svg> sits on the text baseline, so icon separators render a few px above the labels' optical center */ display: flex; align-items: center; & svg { width: 0.875rem; height: 0.875rem; flex-shrink: 0; } /* RTL: auto-flip chevron separators */ [dir="rtl"] & svg { scale: -1 1; } } .breadcrumb-page { color: var(--foreground); font-weight: 400; } /* -- Icons / emoji in front of a crumb --------------------------- An <svg> or a <span class="breadcrumb-icon"> (emoji) before the label: link and page line them up on the label's center and size them to the text (1em - so data-size scales them too). */ .breadcrumb-link, .breadcrumb-page { &:has(> :is(svg, .breadcrumb-icon)) { display: inline-flex; align-items: center; gap: 0.375em; } & > svg { width: 1em; height: 1em; flex-shrink: 0; } } .breadcrumb-icon { display: inline-grid; place-items: center; width: 1.15em; height: 1.15em; flex-shrink: 0; line-height: 1; font-style: normal; } .breadcrumb-ellipsis { display: flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; color: var(--muted-foreground); & span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; } } /* -- Accessibility ------------------------------------------ */ @media (prefers-reduced-motion: reduce) { .breadcrumb-link { transition: none; } } @media (prefers-contrast: more) { .breadcrumb-link { text-decoration: underline; } .breadcrumb-page { font-weight: 600; } } @media (forced-colors: active) { .breadcrumb-link { &:hover { forced-color-adjust: none; color: HighlightText; background: Highlight; } } .breadcrumb-page { color: CanvasText; } .breadcrumb-separator { color: GrayText; } }}Comments, ideas or improvements? Edit this page's source on GitHub