Blog · September 23, 2026

How to build a shadow that looks like real light.

A shadow is the one part of a flat interface that claims to be physics. Everything else — a colour, a corner, a weight — is just an assertion, but a shadow says there is a light source over there and this object is floating this far off that surface. Make the claim badly and the eye files the whole frame under "homemade" without ever working out why.

One shadow is the tell

The default move is a single blurred rectangle: one offset, one radius, one alpha of black. It never looks lifted, because a real object casts two things at once. There's a tight, dark band right where it nearly touches the surface — the contact shadow, where almost no light can squeeze in. And there's a wide, pale, shapeless pool from light arriving off everything else in the room. A single blur splits the difference, so it's too soft to read as contact and too dark to read as ambient: a grey rectangle under a card, not a card above a page.

So stop doing it in one layer. Material's elevation model has described this as two lights, key and ambient, for years, and every convincing shadow system arrives at the same split. A working starting point at card scale:

Contact: y-offset 1–2px, blur 2–4px, no spread, alpha around 0.12.
Ambient: y-offset roughly the height you want the object to appear off the surface, blur about twice that offset, spread slightly negative, alpha around 0.08.

So a card sitting "8px up" gets something like 0 1px 3px rgba(…,.12), 0 8px 16px -4px rgba(…,.08). The numbers aren't sacred; the two-layer structure is. Turn the contact layer off on its own and watch the card immediately start to drift — that thin dark line is doing almost all the work of anchoring it.

Blur and opacity trade against each other, non-linearly

The most common way a shadow goes wrong once the structure is right: someone decides it should be softer, doubles the blur radius, and leaves the alpha alone. Now it's grey fog. Blur spreads a fixed amount of ink over an area that grows with the square of the radius, so doubling the radius doesn't halve the darkness — it quarters the density at the centre while smearing the tail far past the object's footprint. When you double the blur, cut the alpha by rather less than half, then trust your eye: the shadow's visible edge has also moved a long way out and is now touching things it shouldn't.

The same arithmetic bites at export time. Shadow parameters are lengths, so if you compose at preview size and rasterise at store size — a 1290×2796 iPhone frame is several times a typical on-screen preview — every offset, blur and spread has to scale by that same factor. Pipelines that scale geometry but pass shadow values through untouched ship exports where the shadow has collapsed into a hairline, or bloomed into a bruise. Render one frame at final size and look at it at 100% before you trust the preview.

One light, one direction, every element

Inside a single frame, every shadow must agree about where the light is. Interfaces have settled on light from above, which is why almost all UI shadows are pure +y with an x-offset of zero. That convention is worth keeping, not because it's more correct but because it's shared: the reader's expectation is already calibrated.

Where this breaks is at the seams: a card with a downward shadow, a button copied from another file with a slight -2px y, an inset field whose inner shadow sits on the bottom edge. Each is invisible alone; together they read as wrong and nobody in the review can name it. If a control is recessed, its inner shadow belongs on the top edge — the light is still above, the surface just went away from it.

Black is a bad shadow colour

Pure black is the default and it's almost never right, for two reasons.

The first is that real shadows aren't the absence of light, only of the key light. Everything bounced off nearby surfaces still lands in there, tinted by those surfaces. On a saturated background a neutral black shadow reads as dirt on the page rather than shade on the surface. Take the background hue, drop its lightness a long way, keep or slightly raise the saturation, and use that — on a warm gold field a shadow pushed toward deep brown looks lit, where the same shape in neutral grey looks like a hole cut in the artwork.

The second is that the alpha you need depends on how light the surface underneath is. 8% black is perfectly visible on near-white and invisible on a mid-tone, so a shadow token built on a white background and reused on a coloured section stops elevating and starts looking pasted on. Shadow alpha is a function of the contrast beneath it, not a constant.

Dark mode doesn't really have shadows

This is the part most design systems learn the hard way. On a dark surface, "darker" has almost nowhere left to go, so a shadow carries hardly any information — you can crank the alpha to 40% and the card still won't lift, because the difference between your surface and your shadow is a handful of levels. Dark themes solve elevation the other way round: higher elevation means a lighter surface fill, with the shadow demoted to a faint contact line that mostly just crisps the edge.

Which is also the practical argument against a true #000000 canvas, covered in more detail in setting white type on dark: at pure black there is no darker value to recede into, so every plane in the frame collapses onto one. Start your darkest value a little above black and the whole depth system has somewhere to stand.

The shadow has to be the shape of the thing

A shadow is a silhouette, and the silhouette includes the corner radius. Fake a card's shadow with a blurred rectangle behind it and the corners leak — four little grey ears poking past a rounded card, subtle enough to survive review and obvious once you know. If you're compositing by hand rather than letting the renderer do it, blur a copy of the actual shape, radius and all. (The radius has its own arithmetic.)

In store screenshots this shows up as one specific cliché: a phone mockup floating on a gradient with a soft grey oval underneath it. An ellipse is not the shadow of a phone. The shadow of a phone is a rounded rectangle, roughly the phone's own outline, offset in the direction the light isn't. The oval is the single fastest way to make an otherwise good frame look like clip art.

Three checks before you ship it

Toggle it. Turn the shadow off. If the hierarchy reads the same without it, it was decoration — delete it, and use a border or a background step instead.

Shrink it. View the frame at about 25%. A good shadow still separates the object from its ground. An over-blurred one dissolves into a grey halo that just dulls the background — and on a store listing, small is where most people see your work.

Desaturate it. Convert the frame to greyscale. Shadows are a lightness effect; if yours vanishes once colour is gone, the alpha was never carrying the elevation.

The short version: two layers, not one — a tight dark contact shadow plus a wide pale ambient one. One light direction for the whole frame. Tint the shadow with the background's hue, and set its alpha against the background's lightness, not a global token. In dark mode, raise the surface instead. Scale offset and blur with the export resolution. And never put an ellipse under a rectangle.

Depth you don't have to hand-tune

The device frames and floating cards in ShotCanvas's templates are built on these rules: layered rather than single, attached to the real rounded silhouette, tinted with the template's accent rather than flat black, and expressed relative to the frame so every offset and blur scales correctly when the export renders at full store resolution instead of preview size. Drop your screens in, pick a template, and the depth comes with it.

Design your screenshot set free Read: corner radius is not a style choice