The neumorphic design trend that swept Dribbble in 2020 looks complex but reduces to a simple CSS pattern. Two box shadows on a colored background that matches the element create the illusion of extruded or inset surfaces.
The CSS pattern
.neumorphic {
background: #e0e0e0;
border-radius: 20px;
box-shadow:
8px 8px 16px #bebebe,
-8px -8px 16px #ffffff;
}
That is the entire technique. A light shadow on one side (simulating a light source) and a dark shadow on the opposite side (simulating a shadow). The background color must match the parent container's background.
Why the background match matters
Neumorphism only works when the element's background is the same color as its container. The illusion is that the element is extruded from the surface, like pushing clay up from a flat sheet. If the element has a different background color, the extrusion illusion breaks and it just looks like a card with two shadows.
body { background: #e0e0e0; }
.neumorphic-raised {
background: #e0e0e0; /* Must match parent */
box-shadow:
8px 8px 16px #bebebe,
-8px -8px 16px #ffffff;
}
.neumorphic-inset {
background: #e0e0e0;
box-shadow:
inset 8px 8px 16px #bebebe,
inset -8px -8px 16px #ffffff;
}
The inset variant creates a pressed-in appearance, useful for toggle states and input fields.
Calculating shadow colors
The light and dark shadow colors are derived from the background color:
function neumorphicShadows(bgColor, intensity = 0.15) {
const r = parseInt(bgColor.slice(1, 3), 16);
const g = parseInt(bgColor.slice(3, 5), 16);
const b = parseInt(bgColor.slice(5, 7), 16);
const darken = (v) => Math.max(0, Math.round(v * (1 - intensity)));
const lighten = (v) => Math.min(255, Math.round(v * (1 + intensity)));
const dark = `#${darken(r).toString(16).padStart(2,'0')}${darken(g).toString(16).padStart(2,'0')}${darken(b).toString(16).padStart(2,'0')}`;
const light = `#${lighten(r).toString(16).padStart(2,'0')}${lighten(g).toString(16).padStart(2,'0')}${lighten(b).toString(16).padStart(2,'0')}`;
return { dark, light };
}
The accessibility problem
Neumorphism has a significant accessibility issue: low contrast. The design relies on subtle shadows rather than borders or color differences to define boundaries. Users with low vision or on low-contrast displays may not perceive the element boundaries at all.
WCAG requires a minimum contrast ratio of 3:1 for UI components. Neumorphic elements often fail this test because the shadow-based boundaries have contrast ratios below 2:1.
The practical compromise: use neumorphism for decorative elements but maintain traditional contrast for interactive elements. Buttons, inputs, and links should have clear boundaries regardless of design trend.
Dark mode neumorphism
Neumorphism works on dark backgrounds too, but the shadow logic inverts. The "light" shadow becomes a slightly lighter shade of the dark background, and the "dark" shadow becomes near-black.
.neumorphic-dark {
background: #2d2d2d;
box-shadow:
8px 8px 16px #1a1a1a,
-8px -8px 16px #404040;
}
For generating neumorphic CSS with customizable colors, shadow distance, blur, and intensity, I built a generator at zovo.one/free-tools/neumorphism-generator. It shows a live preview and outputs the CSS you can copy directly into your project.
I'm Michael Lip. I build free developer tools at zovo.one. 500+ tools, all private, all free.
Top comments (0)