Design systems · Shadows
Drag one light, get a whole shadow scale
Five hand-tuned shadows give you five unrelated shadows. Derive them from one light instead and the set shares an angle, a blur ramp and an opacity ramp. Move the sliders — every level below is recomputed from the same source, and the numbers are the output of the code, not typed by hand.
0° is directly above. The shadow always falls opposite the light — and every level uses this one angle.
A distant light is a point source and casts crisp edges. A near one wraps the object and smears it.
How high level 1 sits above the surface. Everything above it grows from this number.
Drives density inside a fixed band: 0.04–0.24 alpha. Below that a shadow is invisible, above it reads as a grey box.
Elevation is geometric, not linear. Below ~1.05 the levels stop being distinguishable, so it is not a scale any more.
Set this to 1 and watch the shadow turn into a smudge: one layer cannot carry both the umbra and the penumbra.
These are the real values at real pixel sizes. Paste them straight into your stylesheet, your
tailwind.config.js or a token pipeline.
Why one light instead of five shadows
Nobody hand-tunes one shadow and gets it wrong. The problem starts at five. You nudge each level until it looks right on its own, and the finished set looks like five shadows from five different rooms — the angle drifts, the blur ramp is arbitrary, and the opacities stack into grey.
Three constraints do most of the work here, and you can watch each one break if you push the sliders far enough:
- 1. Opacity lives in a band. Past roughly 0.24 alpha a shadow stops reading as depth and becomes a grey box; under 0.04 it is simply not there. Brightness moves inside that band, never outside it.
- 2. One layer cannot hold both umbra and penumbra. The dense core and the wide falloff need different blur and different opacity. That is what the layers slider is showing you.
- 3. Higher things cast fainter shadows. The same light spreads over more area, so density per pixel drops as the level rises — otherwise level 5 turns into a black bar.
The full derivation, including why a shadow cannot be a Figma variable, is in the article: Why your five shadows don't look like one system.
Same maths, inside Figma
This page runs the exact code the plugin runs — same functions, no reimplementation. Inside Figma, Elevation additionally writes the scale into your file as effect styles, so the levels become real, reusable styles instead of numbers you paste per layer. Free to use.
Get Elevation free