X Xerobit

Neumorphism in CSS — Soft UI Box Shadows and Design Patterns

Neumorphism uses two box shadows — one light, one dark — to create soft extruded or inset UI elements. Learn how to implement neumorphic CSS buttons, cards, and inputs with the...

Mian Ali Khalid · · 4 min read
Use the tool
Box Shadow Generator
Visual CSS box-shadow builder. Control offset, blur, spread, color, inset. Multi-layer shadows. Live preview + copyable CSS.
Open Box Shadow Generator →

Neumorphism (soft UI) simulates physical depth by casting two shadows: a light shadow on the top-left and a dark shadow on the bottom-right, on a background that matches the element. The element appears to extrude from or indent into the surface.

Use the Box Shadow Generator to build neumorphic shadows visually.

The neumorphic formula

/* Background and element must share the same color */
:root {
  --bg: #e0e5ec;
  --shadow-light: #ffffff;
  --shadow-dark: #a3b1c6;
}

.card {
  background: var(--bg);
  border-radius: 20px;
  
  /* Extruded (raised) effect: */
  box-shadow:
    8px 8px 16px var(--shadow-dark),
    -8px -8px 16px var(--shadow-light);
}

The key: --bg, --shadow-light, and --shadow-dark are derived from the same base color. Light shadow is a lighter tint; dark shadow is a darker shade.

Generating shadow colors from a base

/* Given base color #e0e5ec: */
/* Light shadow ≈ base + 15% lightness */
/* Dark shadow ≈ base - 15% lightness */

:root {
  --bg: #e0e5ec;
  --shadow-light: color-mix(in srgb, #e0e5ec 70%, white);
  --shadow-dark: color-mix(in srgb, #e0e5ec 70%, #9baacf);
}

Or calculate manually:

Base: #e0e5ec  (hsl: 216, 27%, 90%)
Light: hsl(216, 27%, 100%) → #ffffff
Dark:  hsl(216, 27%, 72%)  → #a3b1c6

Extruded vs pressed states

.button {
  background: #e0e5ec;
  border-radius: 12px;
  cursor: pointer;
  border: none;
  padding: 16px 32px;
  transition: box-shadow 0.15s ease;
  
  /* Default: raised */
  box-shadow:
    6px 6px 12px #a3b1c6,
    -6px -6px 12px #ffffff;
}

/* Pressed: inset shadows */
.button:active {
  box-shadow:
    inset 4px 4px 8px #a3b1c6,
    inset -4px -4px 8px #ffffff;
}

/* Hover: slightly more pronounced */
.button:hover {
  box-shadow:
    10px 10px 20px #a3b1c6,
    -10px -10px 20px #ffffff;
}

Neumorphic input field

.input-field {
  background: #e0e5ec;
  border: none;
  border-radius: 10px;
  padding: 14px 18px;
  font-size: 1rem;
  color: #4a5568;
  outline: none;
  
  /* Inset = field is recessed into surface */
  box-shadow:
    inset 4px 4px 8px #a3b1c6,
    inset -4px -4px 8px #ffffff;
  
  transition: box-shadow 0.2s ease;
}

.input-field:focus {
  box-shadow:
    inset 6px 6px 12px #a3b1c6,
    inset -6px -6px 12px #ffffff;
}

Neumorphic card component

.neo-card {
  background: #e0e5ec;
  border-radius: 24px;
  padding: 32px;
  
  box-shadow:
    12px 12px 24px #b8c2d0,
    -12px -12px 24px #ffffff;
}

.neo-card__icon {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  
  /* Inset icon circle */
  box-shadow:
    inset 4px 4px 8px #b8c2d0,
    inset -4px -4px 8px #ffffff;
}

.neo-card__button {
  background: #e0e5ec;
  border: none;
  border-radius: 12px;
  padding: 12px 24px;
  cursor: pointer;
  
  box-shadow:
    4px 4px 8px #b8c2d0,
    -4px -4px 8px #ffffff;
  
  transition: all 0.15s ease;
}

.neo-card__button:active {
  box-shadow:
    inset 3px 3px 6px #b8c2d0,
    inset -3px -3px 6px #ffffff;
}

Toggle / switch

.neo-toggle {
  width: 64px;
  height: 32px;
  background: #e0e5ec;
  border-radius: 16px;
  position: relative;
  cursor: pointer;
  
  box-shadow:
    inset 3px 3px 6px #a3b1c6,
    inset -3px -3px 6px #ffffff;
}

.neo-toggle::after {
  content: '';
  position: absolute;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  top: 4px;
  left: 4px;
  background: #e0e5ec;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  
  box-shadow:
    3px 3px 6px #a3b1c6,
    -3px -3px 6px #ffffff;
}

.neo-toggle.active::after {
  transform: translateX(32px);
  background: linear-gradient(145deg, #6a9bf4, #4a7ef0);
  box-shadow:
    3px 3px 6px #3a6ad8,
    -3px -3px 6px #7ab0ff;
}

Accessibility considerations

Neumorphism has real accessibility problems:

/* Problem: low contrast on the same background */
/* Solution: add visible border on focus */

.neo-button:focus-visible {
  outline: 3px solid #4a7ef0;
  outline-offset: 2px;
}

/* Use WCAG color contrast checker — neumorphic text
   on the same background often fails AA (4.5:1) */

/* Don't rely solely on shadow depth to indicate state.
   Add color change or icon change for color-blind users */

.neo-button.active {
  box-shadow: inset 4px 4px 8px #a3b1c6, inset -4px -4px 8px #ffffff;
  color: #4a7ef0;  /* Color change too, not just shadow */
}

Related posts

Related tool

Box Shadow Generator

Visual CSS box-shadow builder. Control offset, blur, spread, color, inset. Multi-layer shadows. Live preview + copyable CSS.

Written by Mian Ali Khalid. Part of the Frontend & Design pillar.