Skip to content

Box Shadow Generator

Smooth, layered shadows from a few sliders — or edit every layer by hand. Copy CSS or a Tailwind class.

How it works

box-shadow takes one or more layers, separated by commas:

css
box-shadow: [inset] <x> <y> <blur> <spread> <color>;
  • x / y move the shadow. Positive y pushes it down, as if the light comes from above.
  • blur softens the edge. 0 gives a hard copy of the box — the "Sharp" preset.
  • spread grows or shrinks the shadow before blurring. A negative spread with a large y gives a shadow that peeks out only underneath.
  • inset draws the shadow inside the box, like a pressed button or an input field.

Why one layer looks fake

A real object casts two shadows at once: a small, dark one where it almost touches the surface, and a large, faint one from the light spreading around it. A single box-shadow can only be one of those — either crisp and close or soft and far — so it looks like a sticker.

Smooth mode stacks several layers instead. Each layer doubles the offset and blur of the previous one, and the total darkness is split between them:

css
box-shadow: 0 1px 2px rgb(15 23 42 / 0.064), 0 2px 4px rgb(15 23 42 / 0.064), 0 4px 8px rgb(15 23 42 / 0.064), 0 8px 16px rgb(15 23 42 / 0.064), 0 16px 32px rgb(15 23 42 / 0.064);

Close layers make the contact shadow, far ones the soft falloff. Adding layers makes the shadow smoother, not darker.

Small things that make shadows look right

  • Tint the shadow. Pure black looks grey and dirty on coloured surfaces. A very dark version of the background hue — the default here is slate — blends in.
  • Keep the light consistent. Every shadow on a page should fall the same way. Use one "light from" angle everywhere.
  • Bigger elevation, softer shadow. Things further from the surface cast wider, lighter shadows. Raise elevation and softness together.
  • Dark themes need less. Shadows barely show on dark backgrounds; lighter surfaces and borders do the work there. Check the preview on both surfaces.

Performance

Shadows are painted, and big blurs are expensive to repaint. Animating box-shadow on hover repaints it every frame. The cheaper trick: put the "hover" shadow on a pseudo-element and animate its opacity, which the browser can do on the compositor:

css
.card { position: relative; box-shadow: var(--shadow-sm); } .card::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: var(--shadow-lg); opacity: 0; transition: opacity 200ms; } .card:hover::after { opacity: 1; }