CSS Box Shadow: Examples and Best Practices

Published 2026-05-21

Shadows are how flat screens fake depth. A well-judged box-shadow lifts a card off the page, signals that a button is clickable, and separates a modal from the content behind it. The CSS is simple to write but easy to get wrong — the difference between an elegant interface and an amateurish one often lives in shadow values. Here is how to use box-shadow well.

The syntax

The box-shadow property takes up to five values:

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

box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.1);
            |  |   |   |  |
            |  |   |   |  color (with transparency)
            |  |   |   spread (grow/shrink)
            |  |   blur radius (softness)
            |  vertical offset
            horizontal offset
  • offset-x / offset-y move the shadow horizontally and vertically. Positive Y pushes the shadow down.
  • blur controls softness — 0 is a hard edge, larger values are softer.
  • spread grows (positive) or shrinks (negative) the shadow's size.
  • color is the shadow color, almost always with transparency.

What makes a shadow look natural

Beginners tend to make shadows too dark, too sharp, and too centered. Real shadows follow a few principles:

  • Light comes from above, so shadows fall downward — use a small positive Y offset and little or no X offset.
  • They are soft, so use a meaningful blur rather than a hard edge.
  • They are subtle. Use low-opacity black, like rgba(0,0,0,0.1) to 0.2) — far lighter than people expect.
/* A clean, natural card shadow */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);

Layering shadows for realism

The secret professionals use: combine multiple shadows separated by commas. Layering a tight, darker shadow with a wider, softer one mimics how real light behaves and looks far more polished than a single shadow:

box-shadow:
  0 1px 2px rgba(0, 0, 0, 0.1),
  0 4px 8px rgba(0, 0, 0, 0.08),
  0 16px 24px rgba(0, 0, 0, 0.06);

Inset shadows

Adding the inset keyword puts the shadow inside the element, making it look pressed or carved rather than raised. This is how you create the classic "pressed button" effect or subtle depth inside input fields:

box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15);

A note on performance

Static shadows are cheap to render. Animating them, however, is not — the browser repaints every frame, which can cause jank. For smooth hover effects, the trick is to animate the opacity of a shadow on a pseudo-element, or transition transform instead, rather than animating the box-shadow values directly.

Getting shadow values right is much easier when you can see them change in real time. The generator below lets you tune offset, blur, spread, and color with sliders against a live preview, then copies production-ready CSS — including layered and inset shadows.

Related tool: CSS Box Shadow Generator — Create CSS box shadows visually and copy the code.
Copied!