Breadcrumb
Thymeleaf source
<sl:breadcrumb> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link href="/">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-link href="/components">Components</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-page>Breadcrumb</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Rendered HTML
<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-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/components">Components</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-page" aria-current="page">Breadcrumb</span> </li> </ol></nav>Built from parts
Section titled “Built from parts”A breadcrumb is shadcn/ui’s parts: a nav holding an ordered list of levels, with a separator between them. The last
level is the page shown now.
<sl:breadcrumb> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link th:href="@{/}">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-link th:href="@{/components}">Components</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-page>Breadcrumb</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb><sl:breadcrumb-link> is a link: give it an href or th:href. <sl:breadcrumb-page> is plain text with
aria-current="page". The list wraps onto a second line when there is no room, as on a phone.
In an application shell the breadcrumb goes in the page header, after the sidebar’s trigger and a vertical separator.
A level without a page
Section titled “A level without a page”A level that has no page of its own, such as a group in the sidebar, is plain text in its item:
Thymeleaf source
<sl:breadcrumb aria-label="Breadcrumb with a plain level"> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link href="/">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item>Settings</sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-page>Notifications</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Rendered HTML
<nav class="breadcrumb" aria-label="Breadcrumb with a plain level"> <ol class="breadcrumb-list"> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/">Home</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item">Settings</li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-page" aria-current="page">Notifications</span> </li> </ol></nav>From a list
Section titled “From a list”There is no mode that renders the levels from a list: write them with th:each, and the page shown now after them.
th:block keeps item and separator together:
<sl:breadcrumb> <sl:breadcrumb-list> <th:block th:each="level : ${levels}"> <sl:breadcrumb-item><sl:breadcrumb-link th:href="${level.url}">[[${level.name}]]</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> </th:block> <sl:breadcrumb-item><sl:breadcrumb-page th:text="${title}">Title</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Collapsed levels
Section titled “Collapsed levels”A long trail can leave levels out. An empty <sl:breadcrumb-ellipsis> stands for them; a screen reader says “More
levels”.
Thymeleaf source
<sl:breadcrumb aria-label="Breadcrumb with collapsed levels"> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link href="/">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-ellipsis/></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-link href="/components">Components</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-page>Breadcrumb</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Rendered HTML
<nav class="breadcrumb" aria-label="Breadcrumb with collapsed levels"> <ol class="breadcrumb-list"> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/">Home</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-ellipsis"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <circle cx="12" cy="12" r="1"></circle> <circle cx="19" cy="12" r="1"></circle> <circle cx="5" cy="12" r="1"></circle> </svg> <span class="sl-sr-only">More levels</span> </span> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/components">Components</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-page" aria-current="page">Breadcrumb</span> </li> </ol></nav>With a menu
Section titled “With a menu”Give the ellipsis the levels it stands for, as dropdown menu items, and it becomes a ghost icon button that opens a menu of them, as in shadcn’s example:
Thymeleaf source
<sl:breadcrumb aria-label="Breadcrumb with a menu"> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link href="/">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item> <sl:breadcrumb-ellipsis> <sl:dropdown-menu-item as="a" href="/docs">Documentation</sl:dropdown-menu-item> <sl:dropdown-menu-item as="a" href="/themes">Themes</sl:dropdown-menu-item> <sl:dropdown-menu-item as="a" href="/github">GitHub</sl:dropdown-menu-item> </sl:breadcrumb-ellipsis> </sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-link href="/components">Components</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator/> <sl:breadcrumb-item><sl:breadcrumb-page>Breadcrumb</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Rendered HTML
<nav class="breadcrumb" aria-label="Breadcrumb with a menu"> <ol class="breadcrumb-list"> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/">Home</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <button class="button dropdown-menu-trigger breadcrumb-ellipsis-trigger" type="button" data-variant="ghost" data-size="icon-sm" id="breadcrumb-more-trigger" popovertarget="breadcrumb-more" aria-haspopup="menu" aria-label="Show more levels"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <circle cx="12" cy="12" r="1"></circle> <circle cx="19" cy="12" r="1"></circle> <circle cx="5" cy="12" r="1"></circle> </svg> </button> <div class="dropdown-menu-content" id="breadcrumb-more" role="menu" popover tabindex="-1" x-data="slDropdownMenu" aria-labelledby="breadcrumb-more-trigger"> <a class="dropdown-menu-item" role="menuitem" href="/docs">Documentation</a> <a class="dropdown-menu-item" role="menuitem" href="/themes">Themes</a> <a class="dropdown-menu-item" role="menuitem" href="/github">GitHub</a> </div> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/components">Components</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon breadcrumb-separator-icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="m9 18 6-6-6-6"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-page" aria-current="page">Breadcrumb</span> </li> </ol></nav><sl:breadcrumb-item> <sl:breadcrumb-ellipsis> <sl:dropdown-menu-item as="a" href="/docs">Documentation</sl:dropdown-menu-item> <sl:dropdown-menu-item as="a" href="/themes">Themes</sl:dropdown-menu-item> </sl:breadcrumb-ellipsis></sl:breadcrumb-item>The button is named “Show more levels”; an aria-label replaces it, and any other attribute goes to the button too.
The menu’s id is breadcrumb-more (the button’s breadcrumb-more-trigger): give a second breadcrumb with a menu on the
same page another id. The menu behaves as every dropdown menu: arrow keys, Home, End and
typeahead move through the levels, Enter follows one, Escape closes it and gives the focus back to the button.
Separator
Section titled “Separator”The separator is a chevron that points to the next level: to the left on a right-to-left page (dir="rtl"). Content
of its own replaces it, such as another icon; that content is not turned around.
Thymeleaf source
<sl:breadcrumb aria-label="Breadcrumb with slashes"> <sl:breadcrumb-list> <sl:breadcrumb-item><sl:breadcrumb-link href="/">Home</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator><sl:icon name="slash"/></sl:breadcrumb-separator> <sl:breadcrumb-item><sl:breadcrumb-link href="/components">Components</sl:breadcrumb-link></sl:breadcrumb-item> <sl:breadcrumb-separator><sl:icon name="slash"/></sl:breadcrumb-separator> <sl:breadcrumb-item><sl:breadcrumb-page>Breadcrumb</sl:breadcrumb-page></sl:breadcrumb-item> </sl:breadcrumb-list></sl:breadcrumb>Rendered HTML
<nav class="breadcrumb" aria-label="Breadcrumb with slashes"> <ol class="breadcrumb-list"> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/">Home</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M22 2 2 22"></path> </svg> </li> <li class="breadcrumb-item"> <a class="breadcrumb-link" href="/components">Components</a> </li> <li class="breadcrumb-separator" role="presentation" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"> <path d="M22 2 2 22"></path> </svg> </li> <li class="breadcrumb-item"> <span class="breadcrumb-page" aria-current="page">Breadcrumb</span> </li> </ol></nav>Accessibility
Section titled “Accessibility”- The
navis named “Breadcrumb” (sl.breadcrumb.label); anaria-labelof your own replaces it, which two breadcrumbs on one page need. - The separators are list items hidden from assistive technology, so a screen reader counts only the levels.
- The page shown now has
aria-current="page"and is not a link. shadcn’s addsrole="link"andaria-disabled="true", which a screen reader announces as a link that goes nowhere. - The empty ellipsis reads “More levels”, where shadcn/ui hides it from screen readers.
- In Windows’ high-contrast mode a focused link gets an outline, as the focus ring (a shadow) is gone there.
Messages
Section titled “Messages”| Key | English |
|---|---|
sl.breadcrumb.label |
Breadcrumb |
sl.breadcrumb.more |
More levels |
sl.breadcrumb.more.trigger |
Show more levels |
Left out
Section titled “Left out”A breadcrumb built from the request’s path or from the sidebar’s menu, and structured data (BreadcrumbList) for
search engines.
Attributes
Section titled “Attributes”sl:breadcrumb
Section titled “sl:breadcrumb”sl:breadcrumb declares no props; every attribute passes through.
sl:breadcrumb-list
Section titled “sl:breadcrumb-list”sl:breadcrumb-list declares no props; every attribute passes through.
sl:breadcrumb-item
Section titled “sl:breadcrumb-item”sl:breadcrumb-item declares no props; every attribute passes through.
sl:breadcrumb-link
Section titled “sl:breadcrumb-link”sl:breadcrumb-link declares no props; every attribute passes through.
sl:breadcrumb-page
Section titled “sl:breadcrumb-page”sl:breadcrumb-page declares no props; every attribute passes through.
sl:breadcrumb-separator
Section titled “sl:breadcrumb-separator”sl:breadcrumb-separator declares no props; every attribute passes through.
sl:breadcrumb-ellipsis
Section titled “sl:breadcrumb-ellipsis”| Attribute | Values | Default | Description |
|---|---|---|---|
id | string | — | With content: the menu's id, breadcrumb-more when not set (the button's is <id>-trigger); give a second breadcrumb on the page another one. Without content: the ellipsis's own id. |
Every prop can also be set from an expression: th:id="${...}". Any other attribute passes through to the rendered element, and class is appended.
JavaScript
Section titled “JavaScript”Only the ellipsis with a menu needs any: it is a dropdown menu, which needs Alpine and no plugin. Without it the button still opens the menu (the browser’s popover), without the arrow keys.