39 CSS Breadcrumbs
21 / 39

All 39 in 39 CSS Breadcrumbs

  1. 01Accessible Breadcrumb Navigation with Schema.org Microdata & ARIA
  2. 02Responsive Collapsing CSS Breadcrumb Bar using :has() Selector
  3. 03Adaptive Light & Dark Mode Breadcrumb Bar with CSS Custom Properties
  4. 04E-Commerce Filter & Attribute Breadcrumb Navigation Component
  5. 05Modern Glassmorphism Floating Breadcrumb Bar UI Design
  6. 06Neumorphic Soft UI Breadcrumb Navigation with Dual Box Shadows
  7. 07Sticky Top CSS Navigation Header with Shrinking Breadcrumb Trail
  8. 08Material Design Flat Breadcrumb Navigation Bar
  9. 09Isometric 3D Layered CSS Breadcrumb Navigation
  10. 10Breadcrumb Bar with Built-In Dropdown Sibling Menus
  11. 11Full-Width Block-Style Segmented CSS Breadcrumb Bar
  12. 12CSS Custom-Property Accent-Color Toggle Breadcrumb
  13. 13Seamless Arrow-Cutout CSS3 Breadcrumb Trail
  14. 14Compact Icon-Only Home Node CSS Breadcrumb Bar
  15. 15Segmented Rounded-Outline Pill CSS Breadcrumb
  16. 16Neumorphic Soft Inset-Shadow CSS Breadcrumbs
  17. 17CSS Grid Auto-Fitting Responsive Breadcrumb Trail
  18. 18NFT/Web3 Holographic Shimmer Breadcrumb Component
  19. 19SaaS Marketing Site Gradient Text Breadcrumb Bar
  20. 20Airbnb-Style Filter Chip Breadcrumb Navigation with Icons
  21. 21Editorial Blog Breadcrumb with Animated Wave Underline Hover
  22. 22Developer Docs Breadcrumb with One-Click Path Copy to Clipboard
  23. 23Modern Pure CSS Arrow Breadcrumb Bar using clip-path Polygons
  24. 24Multi-Line Aligned CSS Grid Subgrid Breadcrumb Layout
  25. 25Interactive Breadcrumb Links with Animated CSS Underline Glow
  26. 26Minimalist CSS Breadcrumb with Custom SVG Separators
  27. 27Multi-Step Checkout & Form Wizard CSS Breadcrumb Indicator
  28. 28Pure CSS Ribbon-Style Chevron Breadcrumb Trail
  29. 29Pill-Shape Badge CSS Breadcrumb Bar UI
  30. 30Clean Line-Separator Minimalist CSS Breadcrumbs
  31. 31Gradient Background Glow CSS Breadcrumb Bar
  32. 32Floating Card Shadow CSS Breadcrumb Navigation
  33. 33Truncated Ellipsis Compact CSS Mobile Breadcrumb
  34. 34Inline Bullet-Point Dot Separator CSS Breadcrumb
  35. 35Skewed Parallel Quadrilateral CSS Breadcrumb Bar
  36. 36Outline Border-Only Geometric CSS Breadcrumbs
  37. 37Circular Icon & Numbered CSS Step Breadcrumbs
  38. 38Frosted Glass Dark UI CSS Breadcrumb Component
  39. 39Modern Micro-Interaction Animated Hover Breadcrumbs
Pure CSSMIT licensed

Editorial Blog Breadcrumb with Animated Wave Underline Hover

Editorial publishing breadcrumb in the spirit of Medium, Substack, and NYT — warm cream paper, muted ink serif type, and a signature hover flourish where an inline SVG wave underline draws itself beneath each crumb like a printer's flourish finishing on the page.

Live Demo
Plain CSSTailwind v4
Try it

Build interactive UI like this from scratch: 20 HTML, CSS & JavaScript projects

ZTM · JavaScript Web Projects · 30‑day money-back guarantee · Affiliate link

10% off at checkout with code
Check ZTM Course

The code

<section class="bc-21" aria-label="Editorial blog breadcrumb with wave underline demo">
      <article class="bc-21__frame">
        <nav aria-label="Breadcrumb" class="bc-21__nav">
          <ol class="bc-21__list">
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Home</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Style</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Fashion</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item" aria-current="page">
              <span class="bc-21__link bc-21__link--current">
                <span class="bc-21__label">The Return of Tailored Denim</span>
              </span>
            </li>
          </ol>
        </nav>
        <h1 class="bc-21__headline">The Return of Tailored Denim</h1>
        <p class="bc-21__dek">A quiet revival of pressed seams and structured silhouettes, filed under Style / Fashion.</p>
      </article>
    </section>
.bc-21 {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: clamp(2rem, 6vw, 4rem) clamp(1rem, 4vw, 2.5rem);
  background: oklch(0.97 0.01 85);
  font-family: Charter, 'Iowan Old Style', 'Palatino Linotype', Georgia, 'Times New Roman', serif;
  color: oklch(0.28 0.02 60);
  -webkit-font-smoothing: antialiased;
  --bc-21-ink: oklch(0.42 0.02 60);
  --bc-21-ink-strong: oklch(0.22 0.02 60);
  --bc-21-accent: oklch(0.55 0.14 30);
  --bc-21-draw: 420ms;
  --bc-21-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

.bc-21 *,
.bc-21 *::before,
.bc-21 *::after {
  box-sizing: border-box;
}

.bc-21__frame {
  width: 100%;
  max-width: 62ch;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.bc-21__nav {
  font-size: 0.9375rem;
  line-height: 1.4;
}

.bc-21__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 0.35rem;
}

.bc-21__item {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--bc-21-ink);
}

.bc-21__item + .bc-21__item::before {
  content: "·";
  margin: 0 0.55rem 0 0.2rem;
  color: oklch(0.62 0.02 60);
  font-size: 1.05em;
  line-height: 1;
  transform: translateY(-0.05em);
}

.bc-21__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 0.15rem;
  min-height: 44px;
  color: var(--bc-21-ink);
  text-decoration: none;
  font-style: italic;
  letter-spacing: 0.005em;
  transition: color 220ms var(--bc-21-ease);
  border-radius: 2px;
}

.bc-21__label {
  position: relative;
  display: inline-block;
}

.bc-21__wave {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.35rem;
  width: 100%;
  height: 6px;
  color: var(--bc-21-accent);
  overflow: visible;
  pointer-events: none;
}

.bc-21__wave path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: 0;
  transition: stroke-dashoffset var(--bc-21-draw) var(--bc-21-ease), opacity 180ms var(--bc-21-ease);
}

.bc-21__link:hover,
.bc-21__link:focus-visible {
  color: var(--bc-21-ink-strong);
}

.bc-21__link:hover .bc-21__wave path,
.bc-21__link:focus-visible .bc-21__wave path {
  stroke-dashoffset: 0;
  opacity: 1;
}

.bc-21__link:focus-visible {
  outline: 2px solid var(--bc-21-accent);
  outline-offset: 3px;
}

.bc-21__link--current {
  color: var(--bc-21-ink-strong);
  font-style: normal;
  font-weight: 600;
  cursor: default;
}

.bc-21__link--current .bc-21__wave {
  display: none;
}

.bc-21__headline {
  margin: 0.5rem 0 0;
  font-size: clamp(1.75rem, 4vw, 2.4rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--bc-21-ink-strong);
}

.bc-21__dek {
  margin: 0;
  font-size: 1rem;
  font-style: italic;
  color: var(--bc-21-ink);
  line-height: 1.55;
  max-width: 48ch;
}

@media (prefers-reduced-motion: reduce) {
  .bc-21__wave path {
    transition: opacity 160ms linear;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .bc-21__link {
    transition: none;
  }
}

@media (prefers-color-scheme: dark) {
  .bc-21 {
    background: oklch(0.19 0.01 70);
    color: oklch(0.82 0.02 80);
    --bc-21-ink: oklch(0.74 0.02 80);
    --bc-21-ink-strong: oklch(0.93 0.02 85);
    --bc-21-accent: oklch(0.78 0.14 60);
  }

  .bc-21__item + .bc-21__item::before {
    color: oklch(0.55 0.02 70);
  }
}
/* No JavaScript — CSS transitions stroke-dashoffset from 100 to 0 on :hover and :focus-visible, drawing the wave underline in beneath each crumb. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Breadcrumb from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Editorial Blog Breadcrumb with Animated Wave Underline Hover
Source: https://codefronts.com/navigation/css-breadcrumbs/wave-underline/

Editorial publishing breadcrumb in the spirit of Medium, Substack, and NYT — warm cream paper, muted ink serif type, and a signature hover flourish where an inline SVG wave underline draws itself beneath each crumb like a printer's flourish finishing on the page.
## HTML
```html
<section class="bc-21" aria-label="Editorial blog breadcrumb with wave underline demo">
      <article class="bc-21__frame">
        <nav aria-label="Breadcrumb" class="bc-21__nav">
          <ol class="bc-21__list">
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Home</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Style</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item">
              <a class="bc-21__link" href="#">
                <span class="bc-21__label">Fashion</span>
                <svg class="bc-21__wave" aria-hidden="true" viewBox="0 0 60 6" preserveAspectRatio="none">
                  <path d="M0 3 Q 15 0, 30 3 T 60 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" pathLength="100" vector-effect="non-scaling-stroke"/>
                </svg>
              </a>
            </li>
            <li class="bc-21__item" aria-current="page">
              <span class="bc-21__link bc-21__link--current">
                <span class="bc-21__label">The Return of Tailored Denim</span>
              </span>
            </li>
          </ol>
        </nav>
        <h1 class="bc-21__headline">The Return of Tailored Denim</h1>
        <p class="bc-21__dek">A quiet revival of pressed seams and structured silhouettes, filed under Style / Fashion.</p>
      </article>
    </section>
```
## CSS
```css
.bc-21 {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: clamp(2rem, 6vw, 4rem) clamp(1rem, 4vw, 2.5rem);
  background: oklch(0.97 0.01 85);
  font-family: Charter, 'Iowan Old Style', 'Palatino Linotype', Georgia, 'Times New Roman', serif;
  color: oklch(0.28 0.02 60);
  -webkit-font-smoothing: antialiased;
  --bc-21-ink: oklch(0.42 0.02 60);
  --bc-21-ink-strong: oklch(0.22 0.02 60);
  --bc-21-accent: oklch(0.55 0.14 30);
  --bc-21-draw: 420ms;
  --bc-21-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

.bc-21 *,
.bc-21 *::before,
.bc-21 *::after {
  box-sizing: border-box;
}

.bc-21__frame {
  width: 100%;
  max-width: 62ch;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.bc-21__nav {
  font-size: 0.9375rem;
  line-height: 1.4;
}

.bc-21__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 0.35rem;
}

.bc-21__item {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--bc-21-ink);
}

.bc-21__item + .bc-21__item::before {
  content: "·";
  margin: 0 0.55rem 0 0.2rem;
  color: oklch(0.62 0.02 60);
  font-size: 1.05em;
  line-height: 1;
  transform: translateY(-0.05em);
}

.bc-21__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 0.15rem;
  min-height: 44px;
  color: var(--bc-21-ink);
  text-decoration: none;
  font-style: italic;
  letter-spacing: 0.005em;
  transition: color 220ms var(--bc-21-ease);
  border-radius: 2px;
}

.bc-21__label {
  position: relative;
  display: inline-block;
}

.bc-21__wave {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.35rem;
  width: 100%;
  height: 6px;
  color: var(--bc-21-accent);
  overflow: visible;
  pointer-events: none;
}

.bc-21__wave path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: 0;
  transition: stroke-dashoffset var(--bc-21-draw) var(--bc-21-ease), opacity 180ms var(--bc-21-ease);
}

.bc-21__link:hover,
.bc-21__link:focus-visible {
  color: var(--bc-21-ink-strong);
}

.bc-21__link:hover .bc-21__wave path,
.bc-21__link:focus-visible .bc-21__wave path {
  stroke-dashoffset: 0;
  opacity: 1;
}

.bc-21__link:focus-visible {
  outline: 2px solid var(--bc-21-accent);
  outline-offset: 3px;
}

.bc-21__link--current {
  color: var(--bc-21-ink-strong);
  font-style: normal;
  font-weight: 600;
  cursor: default;
}

.bc-21__link--current .bc-21__wave {
  display: none;
}

.bc-21__headline {
  margin: 0.5rem 0 0;
  font-size: clamp(1.75rem, 4vw, 2.4rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--bc-21-ink-strong);
}

.bc-21__dek {
  margin: 0;
  font-size: 1rem;
  font-style: italic;
  color: var(--bc-21-ink);
  line-height: 1.55;
  max-width: 48ch;
}

@media (prefers-reduced-motion: reduce) {
  .bc-21__wave path {
    transition: opacity 160ms linear;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .bc-21__link {
    transition: none;
  }
}

@media (prefers-color-scheme: dark) {
  .bc-21 {
    background: oklch(0.19 0.01 70);
    color: oklch(0.82 0.02 80);
    --bc-21-ink: oklch(0.74 0.02 80);
    --bc-21-ink-strong: oklch(0.93 0.02 85);
    --bc-21-accent: oklch(0.78 0.14 60);
  }

  .bc-21__item + .bc-21__item::before {
    color: oklch(0.55 0.02 70);
  }
}
```

## JavaScript
```js
/* No JavaScript — CSS transitions stroke-dashoffset from 100 to 0 on :hover and :focus-visible, drawing the wave underline in beneath each crumb. */
```

How this works

Each crumb link contains an inline SVG with a single quadratic-bezier path (M0 3 Q 15 0, 30 3 T 60 3) drawn in currentColor. The path uses the pathLength="100" attribute so stroke-dasharray and stroke-dashoffset can be reasoned about as percentages instead of pixel arc-lengths. At rest the wave sits at stroke-dashoffset: 100 — fully retracted, invisible. On :hover and :focus-visible the dashoffset transitions to 0 across ~420ms with a soft cubic-bezier ease-out, drawing the wave in left-to-right like ink being laid down. The SVG is absolutely positioned beneath the text baseline so it never disturbs the crumb's own line-box.

Typography leans on a Georgia-first serif stack (Charter, 'Iowan Old Style', Georgia, serif) sized at 15px with generous letter-spacing to feel like set-in-print body copy. The warm oklch cream background pairs with a muted ink foreground for that broadsheet feel. Semantics stay strict: <nav aria-label="Breadcrumb"> wraps an ordered list, ::before pseudos render the · separators (hidden from AT via role/aria patterns baked into the list structure), and the final crumb carries aria-current="page". Every link has a 44px hit target through vertical padding, a visible :focus-visible ring, and a prefers-reduced-motion guard that flips the wave to a static fade instead of the draw-in animation.

Make it yours

  • Swap the wave amplitude by editing the SVG path — `Q 15 -1, 30 3 T 60 3` gives a taller crest for a more playful flourish.
  • Change ink color via the `--bc-21-ink` custom property; the wave inherits through `currentColor` automatically.
  • Slow or quicken the draw by adjusting the `--bc-21-draw` duration token (default 420ms) — 700ms feels calligraphic.
  • For a dropcap on Home, uncomment the `.bc-21__item:first-child .bc-21__link::first-letter` block to enlarge the H.

Gotchas — read before shipping

  • Set `stroke-width` in absolute units and pair with `vector-effect: non-scaling-stroke` — otherwise the wave thins visibly when users zoom or on hi-dpi Retina rendering.
  • The `pathLength="100"` attribute normalizes the arc so `stroke-dasharray: 100` works — omit it and the dashoffset math depends on the real Bezier arc length, which varies per browser.
  • Always ship a Georgia fallback in the serif stack; Charter and Iowan Old Style only exist on Apple platforms, and a bare `serif` keyword lands on Times New Roman on Windows, which reads too newsprint-heavy.

Browser support

ChromeSafariFirefoxEdge
111+15.4+113+111+

Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 56+.

SVG stroke-dasharray transitions are baseline everywhere since 2018. The stroke-dashoffset animation is the workhorse — no JS, no @property, no view-timeline required.

Techniques used in this demo

Search CodeFronts

Loading…