Skip to content

Box Shadow Generator

Composes layered box and text shadows with a live preview and emits the CSS.

Composes a shadow out of layers and emits it as `box-shadow`, `text-shadow` or a `drop-shadow()` filter. The thing worth knowing is that one layer is almost never right: a real shadow is a tight dark contact term plus a wide faint ambient one, and a single shadow can only be one of them. The page nags about that, and tells you which parts of a layer the target property cannot express.

🔒 Runs entirely in your browsershadowcssgenerator
Card
Apply to
  • Layer 1
  • Layer 2

Presets

The offsets grow roughly linearly with elevation and the blur with its square root, which is what a point light above a plane actually produces. The opacity falls as the shadow grows — the same occlusion spread over more area — and getting that backwards is what makes hand-tuned shadows look like smudges.

CSS

box-shadow: 0px 1px 3px rgb(0 0 0 / 0.1), 0px 4px 8px -2px rgb(0 0 0 / 0.08);

How to use it

  1. Say what it is going on

    `box-shadow` for a card or a button, `text-shadow` for type, `drop-shadow()` for anything with real transparency — an icon or a cut-out PNG. The preview changes to match, so you are always looking at the right thing.

  2. Start from a preset

    They are two-layer stacks with the offsets growing linearly with elevation, the blur with its square root, and the opacity falling as the shadow spreads. That last one is the part people get backwards by hand, and getting it backwards is what makes a shadow look like a smudge.

  3. Set the surface colour to the one you actually have

    A shadow tuned on white is too weak on a grey page and too strong on a dark one. The surface swatch is there so you tune against the background the component will really sit on.

  4. Adjust the layers

    Offset, blur, spread and colour per layer, and an inset checkbox. Type the colour rather than using the swatch when you need alpha — shadow colours are almost always translucent, and the native colour input cannot represent that.

  5. Copy the declaration

    The property name changes with the target, so what you copy is ready to paste as it stands.

Common questions

My inset and spread vanished when I switched target. Where did they go?

They were dropped, and the page says so above the output. `text-shadow` has no inset and no spread in its grammar — it takes an x, a y, a blur and a colour, full stop. `drop-shadow()` has no inset and no spread either. Emitting them anyway would produce a declaration the browser discards entirely, which is worse than losing the part that cannot survive.

Why does the colour swatch not match what I typed?

The swatch is `<input type="color">`, which only understands `#rrggbb` and has no alpha at all. It shows a best-effort hex of whatever you typed, and the text field stays authoritative. Edit the text when the value has an alpha in it.

Is `drop-shadow()` just a slower `box-shadow`?

No, it answers a different question. `box-shadow` traces the border box, so a transparent PNG gets a rectangle. `drop-shadow()` follows the alpha channel, so it traces the actual shape. It does cost a compositing pass, and it cannot do inset or spread, so use it when the shape matters and `box-shadow` otherwise.

How many layers is too many?

Two or three does everything a UI needs. Every layer is another blur the compositor runs on every paint, and a six-layer shadow on a list of two hundred rows is a measurable frame-rate cost on a phone. The presets stop at three for that reason.

Feed it from

Next

These accept what this tool produces, so the result can go straight in.