DEV Community

Snappy Tools
Snappy Tools

Posted on

CSS Box Shadow: The Complete Guide to Shadows, Layers, and Design Patterns

box-shadow is one of CSS's most versatile properties. Its syntax has six parameters and supports multiple layered shadows — which makes it powerful and also easy to get wrong. Here's everything you need to know.

The syntax

box-shadow: offset-x offset-y blur-radius spread-radius color;
box-shadow: offset-x offset-y blur-radius spread-radius color inset;
Enter fullscreen mode Exit fullscreen mode
  • offset-x: Horizontal offset. Positive = right, negative = left.
  • offset-y: Vertical offset. Positive = down, negative = up.
  • blur-radius: How blurry the shadow is. 0 = sharp edge. Larger = softer. Default: 0.
  • spread-radius: Expands or shrinks the shadow. Positive = larger, negative = smaller. Default: 0.
  • color: Shadow color. Default: the text color (currentColor).
  • inset: Keyword. Converts the shadow from outside to inside (inner shadow).

Building intuition for the parameters

Just offset — a hard shadow:

box-shadow: 8px 8px 0 0 #2f855a;
Enter fullscreen mode Exit fullscreen mode

Zero blur, zero spread. Creates a retro/flat design effect.

Soft drop shadow (most common):

box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
Enter fullscreen mode Exit fullscreen mode

Centered (no horizontal offset), some blur, slight transparency.

Spread positive vs negative:

/* Shadow bleeds out past element edges */
box-shadow: 0 4px 12px 4px rgba(0, 0, 0, 0.15);

/* Shadow is smaller than element (inward) */
box-shadow: 0 4px 12px -4px rgba(0, 0, 0, 0.15);
Enter fullscreen mode Exit fullscreen mode

Negative spread is useful for creating a tight, contained shadow that doesn't bleed outward.

Inset shadow:

/* Inner shadow — top of element looks pressed in */
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);

/* Inset works as a "pressed" button state */
button:active {
  box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.3);
}
Enter fullscreen mode Exit fullscreen mode

Multiple layered shadows

CSS allows comma-separated shadows. They stack, with the first listed shadow on top:

/* Two shadows for depth */
box-shadow:
  0 2px 4px rgba(0, 0, 0, 0.1),   /* close shadow */
  0 8px 20px rgba(0, 0, 0, 0.08); /* ambient shadow */

/* Three-layer depth (material design style) */
box-shadow:
  0 1px 3px rgba(0, 0, 0, 0.12),
  0 1px 2px rgba(0, 0, 0, 0.24);
Enter fullscreen mode Exit fullscreen mode

Design patterns

Flat / retro shadow:

.card {
  box-shadow: 4px 4px 0 0 #1a202c;
}

/* Hover: shift to look "pressed" */
.card:hover {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 0 #1a202c;
}
Enter fullscreen mode Exit fullscreen mode

Soft, elevated card (Material Design):

/* Resting elevation */
.card {
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.12),
    0 1px 2px rgba(0, 0, 0, 0.08);
}

/* Hover: increase elevation */
.card:hover {
  box-shadow:
    0 10px 20px rgba(0, 0, 0, 0.15),
    0 3px 6px rgba(0, 0, 0, 0.10);
}
Enter fullscreen mode Exit fullscreen mode

Neumorphic / soft UI:

.neu {
  background: #e0e5ec;
  box-shadow:
    6px 6px 12px #b8bec7,
    -6px -6px 12px #ffffff;
}

.neu:active {
  box-shadow:
    inset 6px 6px 12px #b8bec7,
    inset -6px -6px 12px #ffffff;
}
Enter fullscreen mode Exit fullscreen mode

Neumorphism requires: a neutral mid-tone background, a dark shadow in one direction and a light/white shadow in the opposite direction. The background color must match the page background.

Glow effect:

/* Colored glow */
.glow-green {
  box-shadow:
    0 0 10px rgba(47, 133, 90, 0.5),
    0 0 20px rgba(47, 133, 90, 0.3),
    0 0 40px rgba(47, 133, 90, 0.1);
}
Enter fullscreen mode Exit fullscreen mode

Layering the same color at different spread/blur values creates a gradual glow.

Inner ring (focus ring):

/* Visible focus ring using inset */
button:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 2px white,
    inset 0 0 0 4px #2f855a;
}
Enter fullscreen mode Exit fullscreen mode

This creates a two-color focus ring without using outline.

Border substitute (for rounded corners):

/* box-shadow instead of border (doesn't affect layout) */
.card {
  border-radius: 12px;
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.12),
    0 0 0 1px rgba(0, 0, 0, 0.08); /* subtle border */
}
Enter fullscreen mode Exit fullscreen mode

Using box-shadow for borders means no layout shift (shadow doesn't occupy space in the box model, unlike border).

Using CSS variables for consistent shadows

:root {
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.08);
  --shadow-lg: 0 10px 30px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.08);
  --shadow-xl: 0 20px 40px rgba(0,0,0,0.15), 0 8px 16px rgba(0,0,0,0.10);
}

.card { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-xl); }
Enter fullscreen mode Exit fullscreen mode

This is how Tailwind CSS handles shadows — predefined variable-based levels.

Generating box shadows

Composing multi-layered shadows by hand is tedious — especially for neumorphic effects or precise glow layering. An online CSS box shadow generator lets you adjust all parameters with sliders and see the result live, then copy the CSS. Look for one that supports multiple shadow layers and has an inset toggle.

Performance

box-shadow is a paint property — changes to it trigger repaint but not layout. It's one of the safer properties to animate (compared to width/height which trigger layout).

For smooth animations, use transform combined with box-shadow changes, and add will-change: box-shadow if the element animates frequently:

.card {
  transition: box-shadow 0.2s ease, transform 0.2s ease;
  will-change: transform;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
Enter fullscreen mode Exit fullscreen mode

Avoid: Animating filter: drop-shadow() — it's significantly more expensive than box-shadow for most use cases.


box-shadow rewards experimentation. Start with a single soft shadow, then layer in complexity once you have the basic effect working. The real power is in multi-layer composition — that's where most of the interesting design patterns live.

Top comments (0)