Free CSS box-shadow builder
Box shadow generator with a real layer stack
Build a box-shadow the way a design system does it — as a list. Free, and no account stands between you and it: stack up to 10 comma-separated layers, each with its own offset, blur, spread, color, alpha and inset flag, and drag them into the order they should paint in. Seven presets load the ramps that shipped in Tailwind and Material Design 2 rather than invented numbers, and pasting a declaration you already have reloads every slider from it.
- 100% free
- No signup
- Up to 10 layers
- 7 elevation presets
- Paste CSS back in
Shadow list — the first row paints on top
- 1
- 2
CSS
box-shadow: 0px 4px 6px -1px rgba(15, 23, 42, 0.12),
0px 12px 24px -8px rgba(15, 23, 42, 0.18);2 of 10 layers · 0 inset · widest blur 24px · 109 characters
Press Ctrl+V anywhere on the page to drop in a box-shadow declaration to load it back into the sliders — no need to click the field first.
How to generate a box shadow
Three steps from a flat rectangle to a declaration you can paste into a stylesheet.
Start from a ramp instead of from zero
Pick one of the seven presets down the left: Tailwind shadow-md and shadow-xl, Material Design 2 elevation 4dp with its umbra, penumbra and ambient parts, a six-layer ramp that doubles 1px to 32px at 7% opacity each, a hairline that spreads 1px with no blur, a two-layer inset well, or a two-ring focus outline. Each one fills the layer list, so you tune something plausible rather than guess four numbers at once.
Tune each layer, and reorder if they overlap
Every row is one comma-separated shadow with its own offset-x, offset-y, blur, spread and alpha, plus a color swatch and an inset checkbox. Row 1 paints on top of row 2, so a tight dark layer belongs above a wide soft one — the arrows move a row up or down when that order is wrong. Change the card color, its corner radius and the surface behind it, because a shadow that looks right on white can vanish on a slate background.
Copy the declaration, or paste one in to go the other way
Copy CSS puts the whole multi-line box-shadow declaration on your clipboard, formatted one layer per line so a code review can read it. The traffic runs both ways: paste a box-shadow you already have — from a stylesheet, from devtools, in px, rem or em — and the sliders take its values, which is the fastest way to adjust a shadow somebody else wrote.
Technical specifications
| Layers per element | Up to 10 comma-separated shadows; the first in the list paints on top of the ones after it |
|---|---|
| Values per layer | Four lengths — offset-x, offset-y, blur radius, spread radius — plus a color, an alpha and the optional inset keyword |
| Slider ranges | Offsets −80 to +80px, blur 0 to 120px, spread −60 to +60px, alpha 0-100% in 1% steps |
| Presets | 7 — hairline, Tailwind shadow-md, Tailwind shadow-xl, Material Design 2 elevation 4dp, a 6-layer 1→32px ramp, an inset well and a two-ring focus outline |
| Blur maths | CSS Backgrounds 3 defines the blur as a Gaussian of standard deviation half the radius, so a 24px blur fades across 24px — roughly 12px outside the shadow edge and 12px inside it |
| CSS input | Paste any box-shadow declaration to reload the sliders; inset is detected, and rem and em lengths resolve at the 16px root default before being shown in px |
| Preview | A live DOM node with your declaration applied, rendered by the same shadow rasterizer your visitors will get — not a picture of one, and never sent anywhere to be drawn |
| Cost | Free, no account, and no attribution comment stitched into the CSS you copy |
Frequently asked questions
Why does my inset shadow disappear behind an image?
Because an inset shadow is painted above the element's background but below its content, and a child that fills the box covers it. This bites hardest on a figure wrapping an img: the shadow is being drawn, the image is simply on top of it. Put the inset shadow on a wrapper with the image inside at a smaller size, or move it to a ::after pseudo-element with pointer-events: none stretched over the box.
Does a box shadow take up space in the layout?
No — a shadow is ink only and contributes nothing to the element's box, its line box or the scrollable area of its parent. That is convenient until a parent has overflow: hidden, which clips the shadow at the parent's padding edge and makes half of it vanish for no visible reason. Margin on the shadowed element, or padding on the clipping parent, is the usual fix.
What is the spread radius for, and why do Tailwind's shadows use a negative one?
Spread grows or shrinks the shadow rectangle before the blur is applied, and a negative value pulls its edges inward. Tailwind's shadow-md is 0 4px 6px -1px plus 0 2px 4px -2px precisely so the wide, soft layer does not halo out past the left and right sides of the card: the offset pushes it down, the negative spread trims the sides, and the result reads as a light source above rather than a glow all round.
How many layers can I stack before it costs anything?
Each comma-separated layer is a separate blur pass, so cost scales with layer count times blur radius rather than with either alone. Six layers at 7% opacity apiece is the standard smooth-shadow recipe and is fine on a static card; the same six on forty rows of a scrolling list is where dropped frames start. The builder caps the list at 10, which is well past the point where an extra layer stops being visible.
Why is the shadow square when the card has rounded corners?
It should not be — box-shadow follows the border box including its border-radius, so a square shadow under a rounded card means the radius and the shadow are on two different elements. Check whether the radius sits on an inner wrapper while the shadow sits on the outer one. If the shape you want is not a rectangle at all, the shadow will not follow it, and that is when drop-shadow becomes the right property.
When should I use filter: drop-shadow instead?
Use drop-shadow when the silhouette matters more than the box: it reads the alpha channel of what is painted, so a transparent PNG, an SVG logo or a clipped element casts a shadow shaped like the artwork rather than like its bounding rectangle. The trade-offs are real — drop-shadow takes one blur value and no spread, no inset and no comma-separated list, and it creates a containing block for fixed-position descendants.
Can I animate a box shadow on hover?
You can, and the browser will interpolate the lists layer by layer, padding the shorter one with transparent zero-size shadows so the counts do not have to match. It repaints on every frame though, which is why the smoother pattern is a ::after pseudo-element carrying the larger shadow at opacity 0 and animating only that opacity — the compositor handles it without a repaint.
About elevation and the four numbers in a box shadow
A single box-shadow almost never looks like a shadow. Real light produces a penumbra — a soft edge that gets softer with distance — and one Gaussian blur at one opacity produces a uniform grey smudge instead. That is why every design system ships stacks: Material Design 2 splits elevation into three parts it names umbra, penumbra and ambient, Tailwind pairs a tight layer with a wide one and trims the wide one with a negative spread, and the layered-ramp recipe doubles offset and blur together across six layers at about 7% opacity each. Once you have seen the six-layer version next to the one-layer version at the same total darkness, the flat one stops being usable.
The four lengths do genuinely different jobs and only two of them are obvious. Offset-x and offset-y place the light source. Blur controls the softness, and CSS Backgrounds 3 defines it as a Gaussian whose standard deviation is half the radius, which is why a 24px blur spreads its transition across roughly 24px in total rather than 24px outward. Spread is the one people skip: it resizes the shadow rectangle before blurring, so a negative spread keeps a tall soft shadow from leaking out of the sides of a card, and a positive spread with zero blur gives you a hard ring — which is exactly how a focus outline gets built out of two stacked rings without touching the layout. Because the shadow traces the border box, the corners follow whatever the border radius generator gave you, right down to the eight-value slash syntax.
Where most generators mislead is in offering exactly one shadow and no way back. One shadow encourages the flat smudge; no way back means a shadow already in your codebase has to be retyped before it can be edited, so it never gets edited. This one takes a pasted declaration apart into rows. Two neighboring properties are worth knowing before you reach for this one at all: when the shape is not a rectangle — a clipped polygon, a transparent PNG, an SVG mark — the shadow you want comes from drop-shadow in the CSS filter generator, because it reads alpha instead of the box, and when the thing being lifted is type rather than a surface, the property is a different one with only three lengths and no spread at all — that is the text shadow generator. Assembling the whole control, shadow and radius and states together, is what the CSS button generator is for.
Where the shadow is rendered
Every number on this page is worked out by JavaScript running in the tab you are reading it in. Nothing you type, paste or open is uploaded, logged or kept, which is also why the tools carry on working after you disconnect from the network.
The paste shortcut reads only the text you paste, and only long enough to turn it into slider positions — the declaration is parsed in a function on this page and is never stored, not even in local storage.