Skip to content
Back to Design Hub

Shadow & Border-Radius System

Elevation scales and radius tokens that convey depth and hierarchy consistently.

Design TokensBeginner

Why

Random shadows (10 different blurs) and radii (4px, 6px, 8px, 12px mixed) make a UI look unpolished. A small elevation scale and 3 radii convey depth and grouping without arbitrary choices.

Tokens Studio (formerly Figma Tokens) has 500k+ installs, and the W3C Design Tokens Format Module is nearing candidate recommendation. Tokens enable dark mode, multi-brand theming, and platform parity from a single source.

When

Define shadows and radii alongside the color scale. If you have 5+ shadow definitions, consolidate into an elevation scale of 4-5 levels.

How

1. Elevation scale — none, sm (1px), md (4px), lg (8px), xl (16px) — maps to z-depth meaning 2. Shadow recipe — y-offset = blur/2, opacity 0.05-0.15, single light direction (top-left) 3. Radius scale — sm=4, md=8, lg=12, full=9999 (pill); 3-4 values max 4. Pair by surface — card=md radius+sm shadow, modal=lg radius+lg shadow, dropdown=sm radius+md shadow 5. Dark mode — shadows are invisible on dark; use 1px border + lighter surface instead 6. Tokens — --shadow-{none|sm|md|lg|xl}, --radius-{sm|md|lg|full} 7. Enforce — stylelint bans raw box-shadow and border-radius values

Example

/* shadow-radius-tokens.css */ :root { --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-full: 9999px; --shadow-none: none; --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 8px 0 rgb(0 0 0 / 0.08); --shadow-lg: 0 8px 16px 0 rgb(0 0 0 / 0.10); --shadow-xl: 0 16px 32px 0 rgb(0 0 0 / 0.12); } /* Surface pairing — depth conveyed by radius + shadow together */ .card { border-radius: var(--radius-md); box-shadow: var(--shadow-sm); } .modal { border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); } .dropdown{ border-radius: var(--radius-sm); box-shadow: var(--shadow-md); } .pill { border-radius: var(--radius-full); } /* Dark mode — shadows invisible, use border + surface elevation */ :root[data-theme="dark"] .card { box-shadow: none; border: 1px solid var(--color-border-subtle); background: var(--color-surface-raised); }

Common Problems

  • ⚠Multiple light directions — one shadow goes down-right, another up-left, looks broken
  • ⚠Shadows in dark mode — invisible, elevation lost, modal looks flat against the page
  • ⚠Radius inconsistency — card 8px, its header 6px, the image 12px, looks stitched together

Best Practices

  • ✓One light direction, one shadow recipe — vary only y-offset and blur across the scale
  • ✓In dark mode, replace shadows with borders + surface color elevation
  • ✓Match radius to the parent — inner elements use the same or smaller radius, never larger

FAQ