Neumorphism in CSS: Shadows Guide
What Is Neumorphism?
Neumorphism (soft UI) is a design style that makes elements appear to extrude from or press into their background. The effect is achieved with two opposing box-shadows — one light and one dark — on an element whose background matches the surface beneath it.
The result looks like raised or sunken plastic: soft, tactile, and distinctly different from flat design or traditional material elevation. Popularized around 2020, neumorphism has found a niche in dashboard UIs, music players, and calculator interfaces.
How the Dual Shadow Works
Neumorphism relies on three things being the same color:
- The page background
- The element's background
- The midpoint between the two shadow colors
.neumorphic-raised {
background: #e0e0e0;
border-radius: 16px;
box-shadow:
8px 8px 16px #bebebe, /* dark shadow (bottom-right) */
-8px -8px 16px #ffffff; /* light shadow (top-left) */
}
The dark shadow simulates the area where light is blocked. The light shadow simulates the area where light reflects off the raised surface. Together, they create the illusion of depth.
Inset (Pressed) Variant
Flip the shadows inward for a pushed-in effect:
.neumorphic-pressed {
background: #e0e0e0;
border-radius: 16px;
box-shadow:
inset 8px 8px 16px #bebebe,
inset -8px -8px 16px #ffffff;
}
Generating Neumorphic Shadows
The shadow colors are derived from the background. For a background of #e0e0e0 (HSL: 0, 0%, 88%):
| Shadow Type | Calculation | Result |
|---|---|---|
| Dark | Decrease lightness by ~10% | #bebebe (HSL: 0, 0%, 75%) |
| Light | Increase lightness by ~10% or use white | #ffffff |
The offset and blur values control the depth perception:
| Depth | Offset | Blur | Effect |
|---|---|---|---|
| Subtle | 4px | 8px | Slight raise, clean look |
| Medium | 8px | 16px | Standard neumorphic raised |
| Deep | 12px | 24px | Strong extrusion |
| Extra deep | 16px | 32px | Dramatic, almost 3D |
Practical Components
Neumorphic Button
.neu-button {
background: #e0e0e0;
border: none;
border-radius: 12px;
padding: 12px 28px;
font-size: 1rem;
cursor: pointer;
box-shadow:
6px 6px 12px #bebebe,
-6px -6px 12px #ffffff;
transition: box-shadow 0.15s ease;
}
.neu-button:active {
box-shadow:
inset 4px 4px 8px #bebebe,
inset -4px -4px 8px #ffffff;
}
Neumorphic Input Field
.neu-input {
background: #e0e0e0;
border: none;
border-radius: 12px;
padding: 12px 16px;
font-size: 1rem;
box-shadow:
inset 4px 4px 8px #bebebe,
inset -4px -4px 8px #ffffff;
}
.neu-input:focus {
outline: none;
box-shadow:
inset 4px 4px 8px #bebebe,
inset -4px -4px 8px #ffffff,
0 0 0 2px rgba(100, 100, 255, 0.3);
}
Neumorphic Toggle
.neu-toggle {
width: 60px;
height: 30px;
background: #e0e0e0;
border-radius: 15px;
box-shadow:
inset 4px 4px 8px #bebebe,
inset -4px -4px 8px #ffffff;
position: relative;
cursor: pointer;
}
.neu-toggle::after {
content: '';
position: absolute;
width: 24px;
height: 24px;
top: 3px;
left: 3px;
background: #e0e0e0;
border-radius: 50%;
box-shadow:
3px 3px 6px #bebebe,
-3px -3px 6px #ffffff;
transition: transform 0.2s ease;
}
.neu-toggle.active::after {
transform: translateX(30px);
background: #a78bfa;
}
Limitations and Accessibility
Neumorphism has well-documented accessibility challenges:
Contrast Problems
Because the element's background matches the surface, text on neumorphic elements often has poor contrast. The shadows themselves are low-contrast by design.
| Issue | Impact | Mitigation |
|---|---|---|
| Low text contrast | Fails WCAG AA on many backgrounds | Use dark text, ensure 4.5:1 ratio |
| Shadow visibility | Shadows invisible to some users | Never rely on shadows alone for affordance |
| Toggle states | Hard to distinguish pressed/raised | Add color change or icon shift |
| Color blindness | Depth illusion collapses | Use labels and borders as backup |
Design Guidelines for Accessible Neumorphism
- Always meet 4.5:1 text contrast — even if it means using a darker text color than the aesthetic strictly wants
- Add visible borders — a subtle
1px solid rgba(0,0,0,0.05)helps define boundaries - Use color for state — don't rely solely on shadow direction (raised vs pressed) to show toggles
- Test with high contrast mode — neumorphic elements should degrade gracefully when shadows are removed
Tailwind Implementation
/* Add to tailwind.config.ts theme.extend.boxShadow */
'neu-raised': '8px 8px 16px rgba(190,190,190,0.8), -8px -8px 16px rgba(255,255,255,0.9)',
'neu-pressed': 'inset 8px 8px 16px rgba(190,190,190,0.8), inset -8px -8px 16px rgba(255,255,255,0.9)',
<button class="bg-[#e0e0e0] shadow-neu-raised rounded-xl px-6 py-3 active:shadow-neu-pressed">
Click Me
</button>
When to Use Neumorphism
Neumorphism works best in:
- Low-information-density UIs (dashboards, music players, calculators)
- Settings pages with toggles and sliders
- Visual showcase or portfolio sites
Avoid it for:
- High-density data tables or text-heavy pages
- Forms requiring clear error states
- Apps where accessibility is a hard requirement (government, healthcare)
Related Guides
Try It Yourself
Build neumorphic shadows interactively — tweak both light and dark shadows, adjust offset and blur, and preview raised vs pressed states in real time.