CSS box-shadow: The Complete Guide

The box-shadow property adds depth, elevation, and glow to any element — and stacking multiple shadows is where it gets powerful. This guide covers the syntax, layered shadows, performance tricks, and gives you copy-paste recipes. Want to build them visually? Use the free box shadow generator →

The box-shadow syntax

box-shadow: offset-x offset-y blur spread color;

/* Example */
box-shadow: 4px 4px 12px 0px rgba(0, 0, 0, 0.15);

/* Inset (inner shadow) */
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.2);

Layering multiple shadows

The real power of box-shadow is stacking. Comma-separate multiple shadows to create depth, glow effects, or realistic material design elevation:

/* Material Design elevation 3 */
box-shadow:
  0 1px 3px rgba(0, 0, 0, 0.12),
  0 4px 6px rgba(0, 0, 0, 0.08),
  0 12px 24px rgba(0, 0, 0, 0.06);

/* Neon glow */
box-shadow:
  0 0 10px #8b5cf6,
  0 0 30px rgba(139, 92, 246, 0.4),
  0 0 60px rgba(139, 92, 246, 0.2);
Shadows render in stack order — the first shadow is on top. Put your sharpest, darkest shadow first and softer ambient shadows after.

Live demo

Box Shadow

This box uses a three-layer shadow for realistic depth.

Copy-paste shadow recipes

/* Subtle card */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);

/* Medium elevation */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);

/* Heavy elevation */
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);

/* Colored glow */
box-shadow: 0 4px 20px rgba(139, 92, 246, 0.3);

/* Hard edge (retro) */
box-shadow: 5px 5px 0 #000;

/* Inset pressed button */
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.25);

/* Full surround (no offset) */
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.5);

Performance

box-shadow is painted on the GPU composite layer, so it's cheap to render. But animating it directly (e.g. on hover) forces a repaint. The performant trick is to put the hover shadow on a pseudo-element with opacity: 0 and transition the opacity instead:

.card {
  position: relative;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
  opacity: 0;
  transition: opacity 300ms;
}
.card:hover::after {
  opacity: 1;
}

box-shadow in Tailwind CSS

Tailwind has built-in shadow utilities: shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl. For custom shadows use arbitrary values:

<div class="shadow-[0_4px_20px_rgba(139,92,246,0.3)]">
  Glow card
</div>

Common gotchas

Build shadows visually

Add multiple shadow layers, adjust offset, blur, spread, and color with live preview — copy the CSS in one click.

Open the Box Shadow Generator →

FAQ

Can you have multiple box shadows?

Yes. Comma-separate them: box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 8px 24px rgba(0,0,0,0.08). The first shadow renders on top. Layering 2-3 shadows creates much more realistic depth than a single shadow.

What is an inset shadow?

Adding the inset keyword makes the shadow render inside the element instead of outside. It is commonly used for pressed buttons, input fields, and inner glow effects.

Does box-shadow affect layout?

No. Shadows are purely visual and do not change the element's size or position in the document flow. They can overflow parent containers with overflow: hidden.

How do I animate box-shadow performantly?

Animating box-shadow directly causes repaints. The performant approach is to put the target shadow on a pseudo-element with opacity: 0 and transition the opacity instead — the browser can composite opacity changes on the GPU.

Related tools