Box Shadow Generator — Why Your UI Looks "Flat Cheap"

webdev css box-shadow ui tools

A white card, box-shadow: 2px 2px 0 #000, and suddenly the mockup looks like Bootstrap 2012. Soft UI is not “more blur.” It is stacked light: ambient contact shadow plus a softer directional lift.

Anatomy of a believable shadow

LayerRoleTypical recipe
AmbientContact with surface0 1px 2px rgba(0,0,0,.06)
KeyDirectional lift0 8px 24px rgba(0,0,0,.08)
Optional rimSeparation on dark bg0 0 0 1px rgba(255,255,255,.06)
.card {
  border-radius: 12px;
  background: #fff;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.06),
    0 8px 24px rgba(15, 23, 42, 0.08);
}

Tune stacks in a box shadow generator, then paste into tokens so every card matches.

Elevation scale (keep it boring)

:root {
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md:
    0 1px 2px rgba(15, 23, 42, 0.05),
    0 6px 16px rgba(15, 23, 42, 0.08);
  --shadow-lg:
    0 2px 4px rgba(15, 23, 42, 0.04),
    0 12px 32px rgba(15, 23, 42, 0.12);
}

Buttons at rest: sm. Dropdowns: md. Modals: lg. Map Figma “Elevation/2” to these tokens so marketing and app do not invent different blur languages.

Dark mode, print, and a11y

On near-black, translucent black shadows barely show. Reduce blur/opacity, lift the surface color, or add a hairline highlight:

.card--dark {
  background: #16181d;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.06),
    0 10px 28px rgba(0, 0, 0, 0.45);
}

Shadows often vanish in print and Windows forced-colors mode — keep borders so cards do not dissolve. Focus rings need :focus-visible outlines, not elevation alone.

Performance and nesting

Huge spreads on hundreds of nodes hurt low-end phones. Prefer shadow on the elevated element, not every list row. Avoid stacking heavy shadows on parent and every child — double ambient looks dirty. Elevate the outer surface; keep inner chrome flatter.

Soft UI mistakes checklist

  • Single hard offset with 0 blur
  • Pure #000 at high opacity on white
  • Same token on dark and light
  • Shadows on full-bleed flat sections
  • Unique blur values on every card in one view

Subtle hover lift (translateY(-1px) + --shadow-md) reads as affordance; big jumps feel like bugs. Pair a 1px low-contrast border with soft shadow — many “premium” UIs need both. Ship a small elevation system, not a unique shadow per Figma frame.

Hover, drag, and modal stacks

Interactive elevations should move one step on the scale (sm → md), not jump to a unique blur. Dragging a card? Use md while held and snap back on drop. Modals should sit at lg (or a dedicated overlay token) so they clearly float above page cards — if the modal and the card share the same shadow, the hierarchy collapses.

Avoid animating blur radius on every frame; animate opacity of a pre-defined shadow class or a pseudo-element instead when you need motion.

Colored ambient shadows

Some brands tint shadows toward the primary hue (rgba(37, 99, 235, 0.15)) for glow cards. Use sparingly — tinted shadows on every element look like a neon theme. Reserve colored ambient for promotional hero cards; keep neutral shadows for dense app chrome.

If a designer hands you a screenshot with a huge soft halo, recreate it as two or three layers rather than one 0 40px 80px monster — then dial alpha down until it survives a gray background, not only a pure white artboard.

Focus rings vs shadows

Do not replace :focus-visible outlines with shadows alone. Shadows are decoration; focus rings are accessibility. Keep both jobs separate in the design system.