Box Shadow Generator
The box-shadow property takes up to four lengths and a colour, and only two of them behave the way most people assume. Getting a shadow that looks like light rather than like a grey rectangle is mostly a matter of understanding what blur and spread actually do.
How to use it
- Adjust offset, blur, spread, and colour.
- The preview updates live as you change values.
- Copy the generated CSS.
What each value controls
The syntax is horizontal offset, vertical offset, blur radius, spread radius, colour, with an optional inset keyword.
Taking them in turn:
- Horizontal and vertical offset move the shadow. Positive vertical pushes it down, which is what a light source above the element produces, and is why almost every realistic shadow has a positive vertical offset and a horizontal offset of zero.
- Blur radius softens the edge. It is not a simple feather: the shadow fades across a distance of roughly the blur radius, centred on the shadow edge, so half the blur extends outward and half inward. A blur of 20px produces a gradient about 20px wide, not a 20px halo.
- Spread grows or shrinks the shadow before blurring. Positive spread makes it larger than the element, negative makes it smaller. Negative spread combined with a positive vertical offset is the trick behind a tight, believable shadow, because it stops the blur leaking out at the sides.
- Colour, which should almost never be pure black. Real shadows take on the hue of their surroundings, and a low-opacity black looks like a grey film. rgba with an alpha around 0.1 to 0.2, or a very dark version of the background hue, reads as light rather than as a grey shape.
Layering shadows is what makes them look real
A single shadow is a poor approximation of how light works. Real objects cast a tight, dark contact shadow immediately beneath them and a much softer, wider ambient shadow further out.
Reproducing that means two or more comma-separated shadows on the same property: one with a small offset, small blur, and slightly higher opacity, and another with a larger offset, much larger blur, and lower opacity. The result reads as depth in a way a single shadow does not, and it is what every well-regarded design system does.
The other half of realism is scale. An element that appears close to the surface takes a small, tight shadow; one that appears to float takes a larger, softer, more offset one. Elevation systems in design frameworks are exactly this: a fixed ladder of shadow values so that height is communicated consistently.
Inset shadows
The inset keyword draws the shadow inside the element rather than outside, which produces a recessed or pressed appearance. It is how inputs get their subtle inner edge and how a pressed button state is usually built.
A useful side effect: an inset shadow with zero offset and zero blur but a positive spread renders as a solid inner border that does not affect layout, unlike a real border. It is a common way to add a hairline that can be animated without causing reflow.
The performance cost
A static box-shadow is cheap. Animating one is not.
Changing any shadow value forces the browser to repaint the element and, because the shadow extends beyond the element bounds, the area around it. Doing that sixty times a second on a hover transition is a common source of jank, particularly on large elements and on lower-powered devices.
The standard workaround is to put the shadow on a pseudo-element and animate its opacity instead. Opacity is compositor-driven and does not trigger a repaint, so the transition runs on the GPU. It is more markup for a smoother result, and it is worth it on anything large or frequently hovered.
Large blur radii are expensive even when static, because the browser has to compute a gradient over a large area. A 100px blur on many elements at once is noticeable on a phone.
At a glance
| Syntax | x-offset y-offset blur spread color, optional inset |
|---|---|
| Blur behaviour | Gradient spans roughly the blur radius, centred on the edge |
| Multiple shadows | Comma-separated, first is drawn on top |
| Transmitted | Nothing |
Frequently asked questions
Why does my shadow look like a grey box?
Usually pure black at high opacity with too little blur. Drop the alpha to around 0.1 to 0.2, increase the blur, and add a small negative spread so the shadow does not leak out at the sides.
What does spread actually do?
It grows or shrinks the shadow shape before blurring. Negative spread with a positive vertical offset gives a tight shadow that sits under the element rather than haloing it.
Can I use more than one shadow?
Yes, comma-separated, and you generally should. A tight contact shadow plus a wide soft ambient one reads as real depth; a single shadow rarely does.
Is animating box-shadow expensive?
Yes. Every change repaints the element and the area around it. Animate the opacity of a pseudo-element carrying the shadow instead, which runs on the compositor.