Why one shadow reads as a sticker
Hold a card an inch above your desk under a lamp. The shadow directly beneath it is dark and its edge is crisp. Further out it fades over a wide, soft band. A real shadow has two characters at once, tight and loose, and a single CSS blur can only produce one of them. Pick a small blur and you get the crisp contact edge with no fall-off; pick a large one and you get the soft halo with no weight. Either way the box looks stuck onto the page rather than resting above it.
Tobias Ahlin's article on the subject is the one I send to every designer who asks why their cards look flat, and it names the limitation precisely:
"The box-shadow CSS property isn't exactly built to encourage expressiveness. It essentially produces a blurred silhouette of an object."
Tobias Ahlin, Smoother and sharper shadows with layered box-shadows
A blurred silhouette is exactly what one shadow is: the box's outline, offset, run through a single Gaussian blur. The way out is not a cleverer single value. It is several silhouettes, each blurred by a different amount, stacked so that their edges land at different distances from the box. Ahlin's own summary of the technique is the whole method in one sentence: "We can achieve this effect by creating multiple box-shadows (separating each shadow with a comma), and increasing the offset and blur for every shadow."
How the comma list is painted
The syntax is a comma separated list. What matters is the order, because the browser paints the list back to front: MDN states that "the first specified shadow is on top". The layer you write first is the last one drawn, so it sits over the others. That is the right way round for realism if you write the tight shadow first, because the crisp edge should sit on top of the soft fall-off, not underneath it.
box-shadow:
0 1px 2px rgba(27, 35, 64, 0.06), /* contact: tight, on top */
0 4px 8px rgba(27, 35, 64, 0.06), /* near */
0 12px 24px rgba(27, 35, 64, 0.08), /* mid */
0 32px 64px rgba(27, 35, 64, 0.12); /* ambient: wide, painted first */The ratios that work
Doubling is the pattern I use and the one the generator's Add layer button follows: each new layer takes the active layer's Y offset and blur and doubles them, at two thirds of the opacity. Start at 1 and 2 and you get 1/2, 4/8, 12/24, 32/64. The geometric progression matters because it spreads the edges evenly on a perceptual scale; a linear progression (8, 16, 24, 32) bunches the outer layers together and the stack reads as one thick shadow again.
Opacity goes the other way. The tight layers carry little ink each, because they overlap and would add up to a hard dark rim; the wide layers carry a little more, because their ink is spread thin. Totals in the region of 0.25 to 0.35 across the whole stack are about right on a white page. Above that, the element starts to look like it is under a spotlight.
| Layer | Offset | Blur | Opacity | Job |
|---|---|---|---|---|
| 1 | 0 1px | 2px | 0.06 | Contact edge: says the object touches something |
| 2 | 0 4px | 8px | 0.06 | Near shadow: the first fall-off |
| 3 | 0 12px | 24px | 0.08 | Mid: gives the height |
| 4 | 0 32px | 64px | 0.12 | Ambient: the room's light, wide and faint |
Three layers is often enough for a card at rest; four earns its place on a modal or a hero element that is meant to float. Two is a noticeable improvement over one and costs almost nothing.
Tint and a single light source
Layering fixes the shape of a shadow. Colour fixes its mood. A stack of black layers, however well proportioned, still reads as grey smudge on a coloured page. Josh Comeau's article on designing shadows makes the case for tinting better than I can:
"By matching the hue and lowering the saturation/lightness, we can create an authentic shadow that doesn't have that 'washed out' grey quality."
Josh W. Comeau, Designing Beautiful Shadows in CSS
What this means in practice: take the hue of the surface the shadow falls on, drop the lightness a long way and the saturation a little, and use that as the shadow colour for every layer. On this site the canvas is a cool near-white on hue 268, and every shadow is a dark ultramarine on the same hue at low opacity. The shadows look like they belong to the page because, in colour terms, they do. Comeau also insists on one further discipline: "In general, we should decide on a single light source for all elements on the page." Every layered stack on a page should share the same direction. Once one card's shadow leans left while another's leans right, the illusion of a lit surface collapses no matter how well each stack is built.
Key, ambient and Material elevation
Google's Material Design formalised layering before most of us were doing it by hand. Its elevation system draws every raised surface with three shadows, named for the three parts of a real shadow: the umbra (the dark core), the penumbra (the soft edge) and the ambient shadow (the faint wide glow from the room's light). The Material Components source lists the three opacities as 0.2, 0.14 and 0.12, and a shadow map for each elevation level. Level 2, the resting card, is:
box-shadow:
0 3px 1px -2px rgba(0, 0, 0, 0.2), /* umbra */
0 2px 2px 0 rgba(0, 0, 0, 0.14), /* penumbra */
0 1px 5px 0 rgba(0, 0, 0, 0.12); /* ambient */Two things are worth stealing from it even if you never use Material. The umbra uses a negative spread, so the darkest layer is narrower than the card and only shows beneath it. And the system's own documentation gives the clearest one-line argument for bothering with any of this: shadows "are the only visual cue indicating the amount of separation between surfaces". Without them, a card and a section of page are the same thing. The Material elevation example has the full set of levels as generator states.
Building a layered shadow in the generator
- Start with the default single layer:
0 12px 24pxat 18 per cent. - Set it to the contact layer: Y 1, blur 2, opacity 6. The box will look almost flat. That is correct; this layer is the edge, not the depth.
- Press the plus button. The generator adds a layer at double the offset and blur and two thirds the opacity, and makes it active. Press it twice more.
- Open the Layers row and click each chip to check its values. Nudge the last layer's opacity up to 12 so the ambient glow is visible.
- Switch the canvas to Dark and to an image. If the shadow vanishes on the photo, raise the ambient layer's opacity rather than the contact layer's.
- Copy the CSS, or press Share link to keep the stack for later.
Where layering stops helping
Layering is not free and it is not always right. Each layer is painted separately and blur is the costly part, so a four-layer shadow on two hundred list items is a real paint cost on a low-end phone. On this site the four-layer stack is reserved for the console panel and the readout; the 41 tiles in the preset gallery each wear their real shadow, but at 60 per cent scale, and nothing on the page ever animates a box-shadow value. A flat design that uses shadows only as focus rings or hairlines should stay single-layer; there is nothing to gain. And on a dark surface, shadows of any depth barely read, which is why the dark canvas in the generator exists: it shows you when to stop adding layers and start thinking about a luminous edge instead.
Frequently asked questions
How many box shadows can you stack on one element?
CSS sets no limit, and browsers handle dozens without complaint. Three or four is the sweet spot for realism; the generator allows twelve because the long shadow effect needs that many hard-edged layers. Beyond four soft layers the extra ones stop being visible and only add paint cost.
Which box shadow is on top when there are several?
The first one in the comma separated list. So put the tight, dark contact shadow first and the wide, faint ambient one last. An inset highlight that must stay visible goes first of all.
What is the best ratio for layered box shadows?
Double the vertical offset and the blur with each layer, and keep each layer's opacity low, between about 0.04 and 0.12. Starting from 1px 2px, that gives 1/2, 4/8, 12/24 and 32/64, which is the stack used across this site.
Should layered shadows use the same colour?
Usually yes, tinted toward the surface they fall on. Using one hue at different opacities keeps the layers reading as one shadow. Material Design is the exception, using pure black at three fixed opacities, which works on its white surfaces.
Do multiple box shadows hurt performance?
Each layer is painted separately, and blur is the expensive part, so a four-layer shadow costs more than a single one. It is still cheap to paint once. What hurts is animating any of it; see the performance guide for the pseudo-element crossfade that avoids repainting.
Can I mix inset and outer shadows in one list?
Yes. That is how a glass card gets its bright top edge and its drop shadow from one declaration: an inset 1px white highlight first, then the outer layers.