DEV Community

Snappy Tools
Snappy Tools

Posted on

CSS Box Shadow: The Complete Guide with Examples

CSS box-shadow is one of those properties that looks simple on the surface but has surprising depth. This guide covers everything from the basics to multi-layer shadows, inset shadows, and performance considerations — with ready-to-copy examples throughout.

The Syntax

box-shadow: [offset-x] [offset-y] [blur-radius] [spread-radius] [color];
Enter fullscreen mode Exit fullscreen mode

Each value:

  • offset-x — horizontal shift (positive = right, negative = left)
  • offset-y — vertical shift (positive = down, negative = up)
  • blur-radius — higher = softer/larger shadow (can't be negative)
  • spread-radius — expands or contracts the shadow before blur
  • color — any valid CSS colour, including rgba() for transparency

Two values are the minimum required: offset-x and offset-y.

/* Minimal shadow */
box-shadow: 4px 4px black;

/* Typical card shadow */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
Enter fullscreen mode Exit fullscreen mode

Common Shadow Patterns

Soft / Subtle

Best for cards and containers where you want depth without drama.

box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
Enter fullscreen mode Exit fullscreen mode

Raised / Button

Makes an element look clickable — like a physical button.

box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06);
Enter fullscreen mode Exit fullscreen mode

Floating / Elevated

For modals, dropdowns, or any element that should appear above the page.

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

Deep / Strong

Dramatic elevation — use sparingly.

box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.2);
Enter fullscreen mode Exit fullscreen mode

Inset Shadow

Renders the shadow inside the element, giving a pressed or sunken look.

box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.15);
Enter fullscreen mode Exit fullscreen mode

Useful for input fields, toggle wells, or pressed button states.

Multi-Layer Shadows

You can stack multiple shadows by comma-separating them. They render front-to-back (first value is on top).

/* Two-layer shadow: tight dark + wide light */
box-shadow:
  0 2px 4px rgba(0, 0, 0, 0.2),
  0 8px 24px rgba(0, 0, 0, 0.1);
Enter fullscreen mode Exit fullscreen mode

Multi-layer shadows look more natural than a single shadow because real-world light creates both a sharp contact shadow near the object and a soft diffuse shadow further away.

Spread Radius in Practice

The spread radius is often misunderstood. Positive spread expands the shadow before blur is applied; negative shrinks it.

/* Outline effect (0 blur, spread only) */
box-shadow: 0 0 0 3px #3b82f6;

/* Negative spread + large offset = shadow only at bottom */
box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.3);
Enter fullscreen mode Exit fullscreen mode

The 0 0 0 Xpx color pattern is a useful trick for adding a coloured ring/outline to any element — including images — without affecting layout (unlike outline, which can be clipped).

Colour and Opacity

Avoid hardcoded black shadows. Use rgba() with low alpha for realistic depth:

/* Too harsh */
box-shadow: 0 4px 8px black;

/* Natural */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
Enter fullscreen mode Exit fullscreen mode

For coloured glow effects (useful for interactive elements):

/* Green glow */
box-shadow: 0 0 12px rgba(34, 197, 94, 0.5);

/* Blue focus ring */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.4);
Enter fullscreen mode Exit fullscreen mode

Transition and Animation

box-shadow is animatable. Combine with :hover or :focus transitions for responsive depth:

.card {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s ease;
}

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

Keep transitions under 300ms. Longer delays feel sluggish.

Performance Notes

box-shadow triggers the browser's composite layer — it is painted, not composited. This means:

  • Animating box-shadow is more expensive than animating transform or opacity
  • For animation-heavy UIs, use a pseudo-element with opacity transition as a workaround:
.card::after {
  content: '';
  position: absolute;
  inset: 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.card:hover::after {
  opacity: 1;
}
Enter fullscreen mode Exit fullscreen mode

This way you animate opacity (GPU-composited) instead of box-shadow directly.

Dark Mode Shadows

Box shadows over dark backgrounds often disappear or look harsh. Options:

  1. Use rgba() white shadows for a subtle emboss/lift effect
  2. Reduce shadow opacity — a 0.5 alpha shadow that works on light needs ~0.15 on dark
  3. Add a border instead — often cleaner on dark UIs
@media (prefers-color-scheme: dark) {
  .card {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.08);
  }
}
Enter fullscreen mode Exit fullscreen mode

Quick Reference

Pattern CSS
Soft card 0 1px 3px rgba(0,0,0,0.1)
Raised button 0 4px 6px rgba(0,0,0,0.1)
Floating modal 0 10px 25px rgba(0,0,0,0.15)
Inset (pressed) inset 0 2px 4px rgba(0,0,0,0.1)
Focus ring 0 0 0 3px rgba(59,130,246,0.4)
Coloured glow 0 0 12px rgba(34,197,94,0.5)

Try It Live

Rather than tweaking values by hand, use a visual box shadow generator to dial in the exact look you want. SnappyTools CSS Box Shadow Generator lets you add up to 4 independent shadow layers with live preview, export as CSS, and start from one of 5 presets — all in the browser with no signup required.


Box shadows are one of the easiest ways to add depth and polish to a UI. Master the multi-layer approach and the rgba() opacity technique, and you'll stop reaching for border hacks to create the same effect.

Top comments (0)