Share one light source

Derive every shadow from one ratio so the whole page shares a light.

Josh W. Comeaujoshwcomeau.com
Here's the first trick for cohesive shadows: every shadow on the page should share the same ratio.
Designing Beautiful Shadows in CSSRead article ↗
Josh W. Comeaujoshwcomeau.com
As an element gets closer to the user, the offset should increase, the blur radius should increase, and the shadow's opacity should decrease.
Designing Beautiful Shadows in CSSRead article ↗

Higher elements get more offset and blur, and less opacity.

1 · Three levels of height

Tap an element to raise it. Compare shadow directions.

Shadows by handBad
Dialog
One ratioGood
Dialog
const shadow = (level) => {
  const x = 2 * level;       /* offset grows with height */
  const y = 2 * x;           /* one ratio: 1 : 2 : 4 */
  const blur = 2 * y;
  const alpha = 0.3 / (1 + 0.4 * (level - 1)); /* and fades */
  return `${x}px ${y}px ${blur}px rgb(0 0 0 / ${alpha})`;
};

Why it matters, pros and cons

Why it matters

Shadows read as one light when offset, blur and opacity all move together with height.

Pros

  • One function makes every shadow, so nothing gets tuned by eye.
  • Elevation becomes one number you can reason about and reuse.
  • More offset and softer opacity matches how real shadows spread.

Cons

  • A single shadow layer is still flat; real light needs layers (next page).
  • Black shadows nearly vanish on dark surfaces, however good the ratio.
  • A fixed ratio assumes one light direction for the whole interface.