Most neumorphism generators on the web are one-trick tools — pick a surface color, get a rest-state button with hardcoded black/white shadows. Then you discover the press state is missing, the dark mode is missing, the contrast fails WCAG by default, and the Tailwind export doesn’t exist. This generator was built to fix exactly those gaps.
All three canonical depths — convex (raised), flat, concave (sunken) — live in one editor. All four interactive states — rest, hover, pressed, focus — render live so you can verify the press inverts to inset (the canonical neumorphic feedback) and the focus state shows a visible WCAG-compliant ring. The preview canvas renders the same recipe as a button, card, input, or toggle so you can sanity-check the surface across UI element types, not just one shape.
Three more differences worth calling out. HSL-derived shadow colours — the dual corner shadows are computed from your surface lightness ±10–14, so any custom hex produces a coherent recipe (not just the canonical #e0e5ec). Live WCAG contrast scoring — neumorphism has a notorious accessibility problem; this generator scores AA (4.5:1) and AAA (7:1) live on the inner ink color so you catch failures before you ship to the EU EAA / Section 508 audit. Six export formats — copy plain CSS, SCSS mixin, Tailwind arbitrary-value classes, styled-components, React inline-style, or Vue scoped CSS. Output includes the press inversion, focus-visible ring, and a prefers-reduced-motion guard automatically.
Permalink: every adjustment encodes into the URL hash so you can bookmark a tuned recipe or send it to a teammate. No login, no watermark, no paywall. Free and MIT-licensed.
| Property | Value | What it does |
|---|---|---|
box-shadow (convex) | D D B darkCorner, -D -D B lightCorner | The dual outer shadow. Distance D is the corner offset, Blur B softens the shadows. Dark corner at bottom-right + light corner at top-left = canonical "raised pillow". |
box-shadow (concave) | inset D D B darkCorner, inset -D -D B lightCorner | Inset version of the same recipe. Reads as a sunken well — used for inputs, toggles, and pressed-button states. |
background | linear-gradient(145deg, lighter, darker) | Subtle surface gradient sells the curvature. Reverse the stops for concave depth. Use a flat color for the flat depth mode. |
border-radius | 14–24px | Soft corners are the entire aesthetic. Sub-12px corners read as flat material; 30+ reads as overly-rounded skeumorphic. |
darker shadow color | hsl(base.h, base.s, base.l - 12%) | Derived from your base surface (not hardcoded). Subtracting 10–14 lightness produces the bottom-right corner shadow. Generator does this automatically. |
lighter shadow color | hsl(base.h, base.s, base.l + 10%) | Adding 8–14 lightness gives the top-left highlight. On dark surfaces, push to +14 to keep the highlight visible. |
:active flips to inset | box-shadow: inset …; | The pressed state inverts the shadow direction so the surface "dips in" under the finger. This is the canonical neumorphic press feedback. |
@media (prefers-reduced-motion: reduce) | transition: none | Smooth box-shadow transitions can trigger motion sensitivity. The generator wraps the transition in a reduced-motion query automatically. |
The two-shadow recipe is the entire neumorphic aesthetic. Get the dual corner colors right and the rest follows.
.neu-button {
background: linear-gradient(145deg, #f0f4fa, #c5cad1);
color: #384153;
border-radius: 20px;
padding: 16px 28px;
border: none;
box-shadow:
8px 8px 20px rgba(167, 172, 180, 0.35),
-8px -8px 20px rgba(255, 255, 255, 0.9);
transition: box-shadow .25s ease, transform .15s ease;
}
.neu-button:active {
box-shadow:
inset 8px 8px 20px rgba(167, 172, 180, 0.35),
inset -8px -8px 20px rgba(255, 255, 255, 0.9);
transform: translateY(0.5px);
} .neu-input {
background: linear-gradient(145deg, #c5cad1, #f0f4fa);
color: #1a1a24;
border-radius: 14px;
padding: 14px 18px;
border: none;
outline: none;
box-shadow:
inset 6px 6px 14px rgba(167, 172, 180, 0.35),
inset -6px -6px 14px rgba(255, 255, 255, 0.9);
}
.neu-input:focus-visible {
box-shadow:
inset 6px 6px 14px rgba(167, 172, 180, 0.35),
inset -6px -6px 14px rgba(255, 255, 255, 0.9),
0 0 0 3px rgba(124, 108, 255, 0.4);
} .neu-dark {
background: linear-gradient(145deg, #232432, #1a1b24);
color: #dde0ea;
border-radius: 22px;
padding: 18px 32px;
border: none;
box-shadow:
10px 10px 22px rgba(0, 0, 0, 0.45),
-10px -10px 22px rgba(46, 49, 62, 0.95);
}