The Shack Web Development CSS Box Shadow: A Complete Guide

CSS Box Shadow: A Complete Guide With a Visual Generator

Back to All Posts

CSS box-shadow is one of those properties that looks simple until you actually try to get it right. The syntax has five parameters, supports multiple layered shadows, an inset mode, and can produce everything from a subtle card lift to a dramatic glow effect — if you know what each value does.

This guide breaks down every parameter with real examples. And when you're ready to build your own, the Box Shadow Generator lets you tune values visually and copy the exact CSS — no guesswork.

The Syntax

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

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

All five values in order:

ValueRequiredWhat It Does
offset-xYesHorizontal shadow offset. Positive = right, negative = left.
offset-yYesVertical shadow offset. Positive = down, negative = up.
blur-radiusNo (default 0)How blurry the shadow is. 0 = hard edge, higher = softer.
spread-radiusNo (default 0)How much larger/smaller than the element. Positive = larger, negative = smaller.
colorNo (default black)The shadow colour. Use rgba() for transparency control.

The inset Keyword

Add inset before the values to make the shadow appear inside the element instead of outside:

/* Outer shadow (default) */
box-shadow: 4px 4px 12px rgba(0, 0, 0, 0.2);

/* Inner shadow */
box-shadow: inset 4px 4px 12px rgba(0, 0, 0, 0.2);

Inset shadows are great for pressed button states, input focus rings, and embossed panel effects.

Common Shadow Patterns

Subtle Card Lift

The go-to shadow for card components — barely visible, just enough depth:

box-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 8px 24px rgba(0,0,0,0.10);

Medium Elevation

Modals, dropdowns, popovers — something that clearly floats above the page:

box-shadow: 0 4px 6px rgba(0,0,0,0.07), 0 12px 40px rgba(0,0,0,0.15);

Hard Drop Shadow (Retro/Brutalist)

Zero blur, solid offset — a deliberately flat design aesthetic:

box-shadow: 4px 4px 0px #000000;

Glow Effect

Zero offset, coloured shadow — great for buttons and highlights:

box-shadow: 0 0 20px rgba(0, 212, 170, 0.6);

Focus Ring (Accessibility)

Using box-shadow for focus states instead of outline gives you more styling control while keeping accessibility intact:

button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 112, 243, 0.5);
}

Layered Shadows

You can stack multiple shadows with a comma. This is how designers create realistic depth — real-world shadows aren't uniform, they're a combination of a tight dark shadow close to the object and a soft diffuse shadow further away:

/* Natural multi-layer shadow */
box-shadow:
  0 1px 2px rgba(0,0,0,0.07),
  0 2px 4px rgba(0,0,0,0.07),
  0 4px 8px rgba(0,0,0,0.07),
  0 8px 16px rgba(0,0,0,0.07),
  0 16px 32px rgba(0,0,0,0.07);

Each layer doubles in size while keeping the same opacity, producing a smooth, physically plausible shadow. This technique is behind the shadow systems in Material Design and many modern design systems.

Use rgba() always. A plain black or #000 shadow often looks harsh and artificial. rgba(0,0,0,0.15) gives you a much more natural result that adapts to different background colours.

Animating Box Shadows

Box shadow is animatable, but animating it directly is expensive — it triggers a repaint on every frame. A performance trick is to animate opacity on a pseudo-element, or use the spread radius trick:

/* ❌ Expensive — triggers repaint every frame */
.card {
  transition: box-shadow 0.3s ease;
}
.card:hover {
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}

/* ✅ Better — prepare both states, animate with opacity */
.card {
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(0,0,0,0.18);
}

Pairing translateY with an enhanced shadow on hover gives the illusion that the card is lifting — a satisfying interaction that's become a UI standard.

Spread Radius Tricks

The spread radius is the most underused parameter. A few powerful uses:

  • Border without affecting layout: box-shadow: 0 0 0 2px #accent — adds a visible border that doesn't push other elements around (unlike border which adds to box size).
  • Multiple borders: Stack shadows with different spread radii to simulate multiple borders.
  • Negative spread: Shrink the shadow smaller than the element for a more realistic light source effect.
/* Multi-border using layered box-shadow */
box-shadow:
  0 0 0 2px #fff,
  0 0 0 4px #00d4aa,
  0 0 0 6px #fff;
The Box Shadow Generator lets you add multiple shadow layers, toggle inset, and see the result live. Once you're happy, copy the single CSS line and paste it straight into your stylesheet. Pair it with the CSS Formatter to keep your styles tidy.