# Shadow Scales With Elevation

**SHOULD** · **ID:** `design-shadow-scales-with-elevation` · **Category:** design
**Source:** [Emil Kowalski](https://emilkowalski.com/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/design-shadow-scales-with-elevation

> SHOULD: Scale a shadow to the surface's size and elevation — never reuse one flat shadow at every size. Map the tier to how high it sits: chip → shadow-sm, card → shadow-md, popover → shadow-lg, dialog/sheet → shadow-xl. Shadows read weakly on dark backgrounds, so lean on a border for elevation there.

Bigger, higher surfaces cast larger, softer shadows — never reuse one flat shadow at every size

A shadow is a claim about height. A chip resting on the surface throws a tight, near shadow; a sheet or dialog floating well above the page throws a large, soft, spread one. Reuse a single shadow token at both sizes and the physics contradict the geometry — the small element looks like it is hovering too high, the large one looks pasted flat against the page. This is distinct from two neighbours in this corpus: "Layered Shadows" is about realism within one shadow (ambient + direct light), and "Use Tailwind Default Shadows" is about staying on a consistent scale; this principle is about which rung of that scale a surface earns — proportional to its size and elevation. Practically: map the shadow tier to how high the surface sits (chip → `shadow-sm`, card → `shadow-md`, popover → `shadow-lg`, dialog/sheet → `shadow-xl`), and remember shadows read weakly on dark backgrounds, where a border often carries the elevation instead (see "On Dark, Borders Beat Shadows").

## Rule snippet

```tsx
<span class="shadow-sm">chip</span>
<div class="shadow-xl">dialog / sheet</div>
```

## Bad — do not do this

`design-shadow-scales-with-elevation-bad`

```tsx
export function ShadowScalesWithElevationBad() {
  // One shadow token reused at every size — the mistake this principle warns about.
  const flat = '0 4px 10px rgba(0, 0, 0, 0.22)';
  return (
    <div className="w-full max-w-md py-8">
      <div className="flex items-end justify-center gap-8 rounded-xl bg-muted p-8">
        <div
          className="rounded-md bg-card px-3 py-1.5 text-xs text-foreground"
          style={{ boxShadow: flat }}
        >
          Chip
        </div>
        <div
          className="flex h-36 w-56 items-center justify-center rounded-xl bg-card text-sm text-muted-foreground"
          style={{ boxShadow: flat }}
        >
          Full sheet
        </div>
      </div>
      <p className="mt-6 text-center text-xs text-destructive">
        Same shadow at every size: the chip floats too high, the sheet looks pasted on flat.
      </p>
    </div>
  );
}
```

## Good — do this

`design-shadow-scales-with-elevation-good`

```tsx
export function ShadowScalesWithElevationGood() {
  // Elevation is proportional: a small element sits close to the surface, a large
  // floating one is higher up — so its shadow is larger, softer, and more spread.
  const tight = '0 1px 2px rgba(0, 0, 0, 0.18)';
  const deep = '0 14px 34px -10px rgba(0, 0, 0, 0.30)';
  return (
    <div className="w-full max-w-md py-8">
      <div className="flex items-end justify-center gap-8 rounded-xl bg-muted p-8">
        <div
          className="rounded-md bg-card px-3 py-1.5 text-xs text-foreground"
          style={{ boxShadow: tight }}
        >
          Chip
        </div>
        <div
          className="flex h-36 w-56 items-center justify-center rounded-xl bg-card text-sm text-muted-foreground"
          style={{ boxShadow: deep }}
        >
          Full sheet
        </div>
      </div>
      <p className="mt-6 text-center text-xs text-success">
        Shadow scales with size: a tight shadow keeps the chip grounded, a larger soft one lifts the sheet.
      </p>
    </div>
  );
}
```

## References

- [Emil Kowalski — apple-design skill](https://github.com/emilkowalski/skills/tree/main/skills/apple-design)
- [Material Design 3 — Elevation](https://m3.material.io/styles/elevation/overview)
