39 CSS Breadcrumbs06 / 39

Pure CSSMIT licensed

Neumorphic Soft UI Breadcrumb Navigation with Dual Box Shadows

The soft-UI / neumorphism treatment: breadcrumb nodes appear extruded from a single-colour surface using two opposing box-shadows (a light source and a dark source), and the current crumb presses INWARD with inset shadows. The whole effect is one background colour plus shadow pairs — the defining neumorphic recipe.

Published

Live Demo
Try it

The code

<nav class="bc-06" aria-label="Breadcrumb">
  <ol>
    <li><a href="#">Home</a></li>
    <li><a href="#">Apps</a></li>
    <li><a href="#">Finance</a></li>
    <li><a href="#" aria-current="page">Wallet</a></li>
  </ol>
</nav>
.bc-06 {
  display: grid;
  width: 100%;
  min-height: 100vh;
  --surface: oklch(0.9 0.01 255);
  --dark: oklch(0.78 0.02 255);
  --light: oklch(0.99 0.005 255);
  --accent: oklch(0.5 0.16 265);
  font-family: system-ui,'Segoe UI',sans-serif;
  padding: 40px 30px;
  background: var(--surface);
  place-items: center;
}

.bc-06 * {
  box-sizing: border-box;
}

.bc-06 ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.bc-06 li {
  display: flex;
  align-items: center;
}

.bc-06 li + li::before {
  content: "";
  width: 6px;
  height: 6px;
  margin-right: 16px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: inset 1px 1px 2px var(--dark),inset -1px -1px 2px var(--light);
}

.bc-06 a {
  display: inline-block;
  padding: 9px 16px;
  border-radius: 14px;
  font: 600 13.5px/1 system-ui,sans-serif;
  color: var(--accent);
  text-decoration: none;
  background: var(--surface);
  box-shadow: 5px 5px 10px var(--dark),-5px -5px 10px var(--light);
  transition: box-shadow .2s ease,color .2s ease;
}

.bc-06 a:hover {
  box-shadow: 7px 7px 14px var(--dark),-7px -7px 14px var(--light);
}

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

.bc-06 li[aria-current="page"] a {
  color: oklch(0.4 0.03 255);
  box-shadow: inset 3px 3px 6px var(--dark),inset -3px -3px 6px var(--light);
}

@media (prefers-reduced-motion: reduce) {
  .bc-06 a {
    transition: none;
  }
}
/* No JavaScript — dual mirrored box-shadows extrude each crumb from a same-colour surface; the current page uses inset shadows to press inward. */
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: Neumorphic Soft UI Breadcrumb Navigation with Dual Box Shadows
Source: https://codefronts.com/navigation/css-breadcrumbs/neumorphic-soft-ui-breadcrumb-navigation-with-dual-box-shadows/

The soft-UI / neumorphism treatment: breadcrumb nodes appear extruded from a single-colour surface using two opposing box-shadows (a light source and a dark source), and the current crumb presses INWARD with inset shadows. The whole effect is one background colour plus shadow pairs — the defining neumorphic recipe.
## HTML
```html
<nav class="bc-06" aria-label="Breadcrumb">
  <ol>
    <li><a href="#">Home</a></li>
    <li><a href="#">Apps</a></li>
    <li><a href="#">Finance</a></li>
    <li><a href="#" aria-current="page">Wallet</a></li>
  </ol>
</nav>
```
## CSS
```css
.bc-06 {
  display: grid;
  width: 100%;
  min-height: 100vh;
  --surface: oklch(0.9 0.01 255);
  --dark: oklch(0.78 0.02 255);
  --light: oklch(0.99 0.005 255);
  --accent: oklch(0.5 0.16 265);
  font-family: system-ui,'Segoe UI',sans-serif;
  padding: 40px 30px;
  background: var(--surface);
  place-items: center;
}

.bc-06 * {
  box-sizing: border-box;
}

.bc-06 ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.bc-06 li {
  display: flex;
  align-items: center;
}

.bc-06 li + li::before {
  content: "";
  width: 6px;
  height: 6px;
  margin-right: 16px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: inset 1px 1px 2px var(--dark),inset -1px -1px 2px var(--light);
}

.bc-06 a {
  display: inline-block;
  padding: 9px 16px;
  border-radius: 14px;
  font: 600 13.5px/1 system-ui,sans-serif;
  color: var(--accent);
  text-decoration: none;
  background: var(--surface);
  box-shadow: 5px 5px 10px var(--dark),-5px -5px 10px var(--light);
  transition: box-shadow .2s ease,color .2s ease;
}

.bc-06 a:hover {
  box-shadow: 7px 7px 14px var(--dark),-7px -7px 14px var(--light);
}

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

.bc-06 li[aria-current="page"] a {
  color: oklch(0.4 0.03 255);
  box-shadow: inset 3px 3px 6px var(--dark),inset -3px -3px 6px var(--light);
}

@media (prefers-reduced-motion: reduce) {
  .bc-06 a {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — dual mirrored box-shadows extrude each crumb from a same-colour surface; the current page uses inset shadows to press inward. */
```

How this works

Neumorphism lives or dies by one rule: element and background share the same base colour, and depth comes entirely from two mirrored shadows. Each crumb gets box-shadow:5px 5px 10px var(--dark), -5px -5px 10px var(--light) — a dark shadow bottom-right and a light 'shadow' (really a highlight) top-left — so it reads as gently raised from the surface. The surface, crumbs and text all sit on the same --surface tone; contrast is sculpted by light, not colour.

The current page inverts the physics: box-shadow:inset 3px 3px 6px var(--dark), inset -3px -3px 6px var(--light) carves the node into the surface, the universal soft-UI signal for 'active/pressed'. Hover deepens the extrusion slightly (larger offsets) for tactility. The accessibility caveat is real and handled: neumorphism is inherently low-contrast, so link text uses a darker accent than the surface (not tone-on-tone), and focus rings are a solid accent outline — depth cues are decorative, never the only signal.

Make it yours

  • The two shadow colours are the entire lighting model: derive them from the surface with color-mix() (darker + lighter) so a single --surface edit re-tunes everything.
  • Shadow blur/offset sets softness: 5px/10px is pillowy; 3px/6px is crisp; match to element size.
  • Warm neumorphism: give the light shadow a faint warm tint and the dark a cool one for a more physical feel.
  • Round corners generously (14px+) — hard corners fight the soft-shadow illusion.

Gotchas — read before shipping

  • Contrast is the trap — WCAG text contrast is measured against the surface, and tone-on-tone fails; keep link text a genuinely darker/accented colour, never the surface tone.
  • The element and its background MUST be the same colour, or the dual-shadow illusion collapses into a plain drop shadow.
  • Inset shadows for 'pressed' need enough blur to read; too tight and it looks like a border, not a well.
  • Don't rely on raised-vs-pressed alone to convey current page — pair it with aria-current and a text-weight change.

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 all.

box-shadow (incl. inset) is universal; color-mix() (2023) is optional sugar for deriving the shadow tones. The look works anywhere.

Techniques used in this demo

Search CodeFronts

Loading…