Why most generated shadows look wrong
The default shadow from most generators is symmetrical: box-shadow: 0 4px 6px rgba(0,0,0,0.1). It renders correctly but looks flat and artificial. Real shadows are directional — light comes from above, so shadows fall below and slightly to one side. They also soften as objects rise higher from the surface: a card at 2dp elevation has a tight, dark shadow; a modal at 24dp has a large, diffuse one. Full write-up on shadow realism here.
The two most impactful fixes: (1) Add a small positive Y offset (2–4px for low elevations) to simulate light from above. (2) Use two layered shadows — one tight and dark for the direct shadow, one wide and lighter for ambient light diffusion. Google's Material Design uses exactly this technique for all elevation levels.
Shadow presets by elevation level
| Component | Elevation | CSS |
|---|---|---|
| Subtle card border | Near 0 | 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06) |
| Button (resting) | Low | 0 2px 4px rgba(0,0,0,.10), 0 1px 2px rgba(0,0,0,.08) |
| Dropdown / popover | Medium | 0 4px 12px rgba(0,0,0,.12), 0 2px 4px rgba(0,0,0,.08) |
| Card (hovering) | Medium-high | 0 8px 24px rgba(0,0,0,.12), 0 4px 8px rgba(0,0,0,.08) |
| Modal / dialog | High | 0 20px 48px rgba(0,0,0,.18), 0 8px 16px rgba(0,0,0,.10) |
These are starting points. Adjust opacity based on your background color: shadows on white need less opacity than shadows on light-grey surfaces. Dark mode requires higher opacity (0.3–0.5) because contrast ratios flip.
When to use colored shadows
Colored shadows work well when the surface casting the shadow has a strong hue — a blue card with a blue-tinted shadow, for example. The trick is to use a muted, desaturated version of the color at low opacity rather than the full saturated value. A button with background: #6366f1 (Indigo-500) reads well with box-shadow: 0 4px 14px rgba(99,102,241,0.4). Using the full saturation without reducing opacity makes the shadow look like a glow effect, not an elevation shadow.
