Breadcrumb — .mv-breadcrumb

Pure CSS breadcrumb on nav > ol: chevron, slash or dot separators (silent for screen readers), icons, truncation, and collapsed levels in an anchored native popover.

CategoryNavigation
TypeCSS only (.mv-breadcrumb)
Statusstable
Keywordsbreadcrumb, fil d'ariane, breadcrumbs, navigation, separator, ellipsis, popover

When to use

Avoid when

Install

node scripts/add.mjs breadcrumb --out ./src/marvelous

AI agent with the Marvelous UI MCP server: install_components({ slugs: ["breadcrumb"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Files copied (dependencies included): tokens/tokens.css, core/base.css, components/breadcrumb/breadcrumb.css.

Usage

Canonical markup — start from it and customize with attributes, data-* and CSS variables:

<div style="display:grid;gap:1.75rem;justify-items:start">
  <!-- Chevron (default) with a home icon -->
  <nav class="mv-breadcrumb" aria-label="Breadcrumb">
    <ol>
      <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/></svg>Home</a></li>
      <li><a href="#">Shop</a></li>
      <li><a href="#">Home &amp; garden</a></li>
      <li><span aria-current="page">Lighting</span></li>
    </ol>
  </nav>

  <!-- Slash, collapsed levels in a popover menu -->
  <nav class="mv-breadcrumb" aria-label="Breadcrumb" data-separator="slash">
    <ol>
      <li><a href="#">Documents</a></li>
      <li>
        <button class="mv-breadcrumb-ellipsis" popovertarget="bc-demo-menu" aria-label="Show hidden levels" style="anchor-name:--bc-demo"></button>
        <div class="mv-breadcrumb-menu" id="bc-demo-menu" popover style="position-anchor:--bc-demo">
          <a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>Clients</a>
          <a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>Mercer Group</a>
          <a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>Contracts 2026</a>
        </div>
      </li>
      <li><a href="#">Amendments</a></li>
      <li><span aria-current="page">Amendment No. 3.pdf</span></li>
    </ol>
  </nav>

  <!-- Dot separator, icons before each level -->
  <nav class="mv-breadcrumb" aria-label="Breadcrumb" data-separator="dot">
    <ol>
      <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/></svg>Workspaces</a></li>
      <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>Design team</a></li>
      <li><span aria-current="page"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z"/><path d="M14 2v6h6"/></svg><span class="mv-breadcrumb-truncate">Brand guidelines — final approved version</span></span></li>
    </ol>
  </nav>

  <!-- Boxed, small -->
  <nav class="mv-breadcrumb" aria-label="Breadcrumb" data-variant="boxed" data-size="sm">
    <ol>
      <li><a href="#" aria-label="Home"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/></svg></a></li>
      <li><a href="#">Settings</a></li>
      <li><span aria-current="page">Billing</span></li>
    </ol>
  </nav>
</div>

API

Attributes

NameTypeDefaultDescription
data-separatorchevron | slash | dot | nonechevronSeparator between levels (drawn in CSS, silent for assistive tech).
data-variantboxedWraps the trail in a bordered pill.
data-sizesmSmaller text.
aria-currentpageOn the last level (span or link): current page, emphasized.

CSS classes

NameDescription
mv-breadcrumbOn <nav aria-label="Breadcrumb"> containing an <ol> of <li>.
mv-breadcrumb-ellipsis“…” button (or span) replacing collapsed levels; automatic dots icon when empty.
mv-breadcrumb-menuOn a <div popover>: list of hidden levels, anchored below the button (popovertarget).
mv-breadcrumb-truncateTruncates a long label with an ellipsis.

CSS variables

NameDefaultDescription
--mv-breadcrumb-max12remMax width of a .mv-breadcrumb-truncate label.

Accessibility

<nav> landmark with aria-label, ordered list, aria-current="page" on the current page. Separators are pseudo-elements with empty alt text (content: … / ""), so they are not read. The “…” button has an aria-label and opens a native popover (Escape and outside click close it, focus is handled by the browser). Icon-only links: aria-label required.