How to Add Neumorphism Effect with Pure CSS

Neumorphism, also called soft UI, gives elements a smooth, pillow like depth that looks molded from the same surface. The trick is simple: use the same background color for the page and the element, then add two soft shadows, a darker one to one side, a lighter one to the opposite side. In this tutorial, I will show you how to add the neumorphism effect with pure CSS, explain each part of the code, and give you two complete HTML examples you can paste into a file and open in your browser.

What makes the neumorphism look

Neumorphism depends on three things working together:

  • Same background color on the page and on the component
  • Two shadows, a dark shadow and a light highlight
  • Rounded corners, gentle shapes, and careful contrast

The core CSS is the double shadow. One shadow simulates light falling from the top left, the other simulates the soft lift on the bottom right. Here is a typical raised effect:

box-shadow: 8px 8px 16px #b8bec9, -8px -8px 16px #ffffff;
  • The first shadow is darker; it sits at positive x and y offsets, for example 8px 8px, then a blur 16px, and a darker color.
  • The second shadow is lighter; it sits at the opposite offsets -8px -8px, then the same blur, and a lighter color.

For a pressed in effect, use inset on both shadows:

box-shadow: inset 8px 8px 16px #b8bec9, inset -8px -8px 16px #ffffff;

The light and dark colors should be derived from your base background. If the base is #e6e9ef, a good darker tone is #b8bec9, and a good highlight is near white #ffffff.

The core CSS you will reuse

I like to define variables so I can tweak the look in one place.

:root {
  --bg: #e6e9ef;
  --shadow: #b8bec9;
  --highlight: #ffffff;
  --text: #1f2937;
  --radius: 16px;
}

Then a raised “neo” surface becomes:

.neo {
  background: var(--bg);
  color: var(--text);
  border-radius: var(--radius);
  box-shadow:
    8px 8px 16px var(--shadow),
    -8px -8px 16px var(--highlight);
}

And a pressed version flips to an inset:

.neo--pressed {
  box-shadow:
    inset 8px 8px 16px var(--shadow),
    inset -8px -8px 16px var(--highlight);
}

Two small extras make the effect cleaner:

  • A faint border adds crispness on high DPI screens:
border: 1px solid #ffffff40; /* semi transparent white */
  • A hover or active transition gives a gentle movement:
transition: box-shadow 0.2s ease, transform 0.15s ease;

Now, let us build the examples.

Example 1, a short and quick neumorphic card

This minimal example shows one raised card with a heading and a paragraph. The page background and the card background use the same color, and the soft shadows create depth.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Neumorphism with Pure CSS - Minimal Example</title>
<style>
:root {
--bg: #e6e9ef;
--shadow: #b8bec9;
--highlight: #ffffff;
--text: #1f2937;
--radius: 16px;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Arial, sans-serif;
background: var(--bg);
color: var(--text);
display: grid;
place-items: center;
padding: 24px;
min-height: 100dvh;
}
.neo {
width: min(92vw, 520px);
padding: 24px 28px;
background: var(--bg);
border-radius: var(--radius);
border: 1px solid #ffffff40;
box-shadow:
8px 8px 16px var(--shadow),
-8px -8px 16px var(--highlight);
transition: box-shadow 0.2s ease, transform 0.15s ease;
}
.neo:hover { transform: translateY(-1px); }
.neo h1 { margin: 0 0 10px; font-size: clamp(1.25rem, 3.5vw, 1.75rem); }
.neo p { margin: 0; line-height: 1.6; }
</style>
</head>
<body>
<div class="neo" role="region" aria-label="Neumorphic card">
<h1>Neumorphism with Pure CSS</h1>
<p>This card looks molded from the page. The two soft shadows create depth, the border radius keeps edges friendly, the same background color on the card and page sells the illusion.</p>
</div>
</body>
</html>

Output:

Neumorphic card on a light gray background, soft raised effect with gentle shadows and a short heading and paragraph.

What to notice:

  • The box-shadow uses a dark and a light color. The order matters; keep the dark shadow positive, the light shadow negative to match a top left light source.
  • The border: 1px solid #ffffff40 sharpens edges without breaking the soft look.

If you want to see a pressed state, add a second class. For example:

<div class="neo neo--pressed">...</div>

With this CSS:

.neo--pressed {
  box-shadow:
    inset 8px 8px 16px var(--shadow),
    inset -8px -8px 16px var(--highlight);
}

Example 2, a complete neumorphic UI with buttons and a theme switch

This page shows a small header, a control panel with raised buttons, and a toggle that switches to a dark theme using only CSS. The buttons press in on click via :active, no JavaScript needed.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Neumorphism Effect with Pure CSS - Complete Demo</title>
<style>
:root{
--bg: #e6e9ef;
--shadow: #b8bec9;
--highlight: #ffffff;
--text: #1f2937;
--muted: #475569;
--radius: 16px;
--gap: 14px;
}

*{ box-sizing: border-box; }
html, body { height: 100%; }
body{
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Arial, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100dvh;
display: grid;
grid-template-rows: auto 1fr auto;
}

/* Theme switch using a checkbox and CSS variables */
#theme-toggle { position: absolute; left: -9999px; }
#theme-toggle:checked ~ .page{
--bg: #1e293b; /* slate blue base */
--shadow: #111827; /* deep shadow */
--highlight: #2a3a52; /* gentle highlight */
--text: #e5e7eb;
--muted: #cbd5e1;
}

header{
padding: 14px clamp(14px, 4vw, 28px);
}
.bar{
display: flex; align-items: center; justify-content: space-between;
padding: 12px 16px;
background: var(--bg);
border-radius: var(--radius);
border: 1px solid #ffffff40;
box-shadow:
8px 8px 16px var(--shadow),
-8px -8px 16px var(--highlight);
}
.brand{ font-weight: 800; letter-spacing: 0.2px; }

.switch{
display: inline-grid; grid-auto-flow: column; gap: 8px; align-items: center;
user-select: none; cursor: pointer;
}
.switch .pill{
width: 48px; height: 26px; border-radius: 999px; position: relative;
background: var(--bg);
border: 1px solid #ffffff40;
box-shadow:
4px 4px 8px var(--shadow),
-4px -4px 8px var(--highlight);
transition: box-shadow 0.2s ease;
}
.switch .dot{
position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
background: var(--bg);
border: 1px solid #ffffff40;
box-shadow:
3px 3px 6px var(--shadow),
-3px -3px 6px var(--highlight);
transition: transform 0.2s ease;
}
#theme-toggle:checked ~ .page .switch .dot { transform: translateX(22px); }

main{ padding: clamp(16px, 4vw, 32px); }
.grid{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--gap);
max-width: 1100px;
margin: 0 auto;
}
.panel{
background: var(--bg);
border-radius: var(--radius);
border: 1px solid #ffffff40;
padding: 18px;
box-shadow:
8px 8px 16px var(--shadow),
-8px -8px 16px var(--highlight);
display: grid; gap: 12px;
}
.panel h2{ margin: 0; font-size: 1.1rem; }
.panel p{ margin: 0; color: var(--muted); line-height: 1.55; }

.controls{ display: flex; flex-wrap: wrap; gap: 10px; }
.btn{
display: inline-flex; align-items: center; justify-content: center;
padding: 12px 16px;
min-width: 120px;
border-radius: 12px;
background: var(--bg);
color: var(--text);
border: 1px solid #ffffff40;
box-shadow:
6px 6px 12px var(--shadow),
-6px -6px 12px var(--highlight);
cursor: pointer;
transition: box-shadow 0.15s ease, transform 0.1s ease;
text-decoration: none;
font-weight: 700;
}
.btn:active{
transform: translateY(1px);
box-shadow:
inset 6px 6px 12px var(--shadow),
inset -6px -6px 12px var(--highlight);
}

.input{
display: grid; gap: 6px;
}
.input label{ font-size: 0.9rem; opacity: 0.9; }
.field{
appearance: none;
width: 100%;
padding: 12px 14px;
font: inherit; color: var(--text);
background: var(--bg);
border-radius: 12px;
border: 1px solid #ffffff40;
box-shadow:
inset 6px 6px 12px var(--shadow),
inset -6px -6px 12px var(--highlight);
outline: none;
}
.field:focus{
border-color: #93c5fd;
box-shadow:
inset 6px 6px 12px var(--shadow),
inset -6px -6px 12px var(--highlight),
0 0 0 3px #93c5fd55;
}

footer{
padding: 18px clamp(16px, 4vw, 28px);
text-align: center;
color: rgba(0,0,0,0.6);
}
#theme-toggle:checked ~ .page footer{ color: rgba(255,255,255,0.7); }
</style>
</head>
<body>
<!-- Hidden checkbox drives the theme, the label toggles it -->
<input type="checkbox" id="theme-toggle" aria-label="Toggle dark theme">

<div class="page">
<header>
<div class="bar">
<div class="brand">SoftUI</div>
<label class="switch" for="theme-toggle" aria-label="Theme switch">
<span>Theme</span>
<span class="pill"><span class="dot" aria-hidden="true"></span></span>
</label>
</div>
</header>

<main>
<div class="grid" aria-label="Neumorphic panels">
<section class="panel" aria-labelledby="p1">
<h2 id="p1">Neumorphic Buttons</h2>
<p>Raised by default, pressed on click using the <code>:active</code> selector and inset shadows.</p>
<div class="controls">
<button class="btn" type="button">Primary</button>
<button class="btn" type="button">Secondary</button>
<a class="btn" href="#" role="button">Link Button</a>
</div>
</section>

<section class="panel" aria-labelledby="p2">
<h2 id="p2">Inputs with Soft Depth</h2>
<p>The field is pressed in using <code>inset</code> shadows, focus adds a visible ring for accessibility.</p>
<div class="input">
<label for="name">Your name</label>
<input id="name" class="field" type="text" placeholder="Jane Doe" />
</div>
</section>

<section class="panel" aria-labelledby="p3">
<h2 id="p3">Why it works</h2>
<p>Page and components share the same background, a dark shadow and a light highlight sit on opposite sides, the radius keeps edges gentle.</p>
</section>
</div>
</main>

<footer>
Built with pure CSS, no images, no JavaScript required for the effect.
</footer>
</div>
</body>
</html>

Output:

Neumorphic UI with a header, theme switch, raised buttons, and a pressed input field on a light gray surface.

Live Preview:

See the Pen Neumorphic-2 by Vinish Kapoor (@foxinfotech) on CodePen.

Why these values

  • If the effect looks too strong, lower offsets and blur, for example 6px 6px 12px. If it looks flat, raise them to 10px 10px 20px.
  • Keep the base background neutral. Very saturated backgrounds can make shadows look dirty.
  • For text, use a color that contrasts with the base. I like #1f2937 on light bases, and #e5e7eb on dark bases.

Practical tips for neumorphism with pure CSS

  • Keep contrast readable. Neumorphism is subtle, so bump font weight and consider a thin border to help edges show.
  • Use :active for pressed states on buttons, and :focus or :focus-visible to add clear focus rings for keyboard users.
  • Avoid very large shadow values on mobile, heavy blurs can hurt performance.
  • Try a light source direction and stick to it. If your light comes from top left, keep dark shadows at positive offsets, highlights at negative offsets across the UI.
  • Use variables for colors and spacing so you can swap themes easily.

Closing thoughts

That is how I add the neumorphism effect with pure CSS, from the key shadow recipe to two working examples. The effect comes from a shared background color, a matched pair of shadows, and soft shapes. Start with a simple card, then apply the same pattern to buttons, inputs, and panels. Tweak the offsets, blur, and colors until the depth feels right, small changes make a big difference.

See also: How to Create Glassmorphism Effects Using CSS

Vinish Kapoor
Vinish Kapoor

Vinish Kapoor is a seasoned software development professional and a fervent enthusiast of artificial intelligence (AI). His impressive career spans over 25+ years, marked by a relentless pursuit of innovation and excellence in the field of information technology. As an Oracle ACE, Vinish has distinguished himself as a leading expert in Oracle technologies, a title awarded to individuals who have demonstrated their deep commitment, leadership, and expertise in the Oracle community.

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments