39 CSS Breadcrumbs06 / 39
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
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><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;
}
}.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. */
/* No JavaScript — dual mirrored box-shadows extrude each crumb from a same-colour surface; the current page uses inset shadows to press inward. */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. */
```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--surfaceedit 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-currentand a text-weight change.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 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.