zudo-css

Type to search...

to open search from anywhere

Layered Natural Shadows

CreatedMar 13, 2026UpdatedMar 26, 2026Takeshi Takatsudo

The Problem

Shadows are one of the most important depth cues in UI design, yet AI agents almost always generate a single, flat box-shadow declaration. A single shadow looks artificial because real-world shadows are not uniform blurs. When an object sits on a surface, it casts a tight, dark contact shadow near its base and a softer, lighter shadow that spreads further. A single box-shadow cannot reproduce this layered behavior.

The Solution

Use multiple comma-separated box-shadow values with progressively increasing blur radius and vertical offset. Each layer represents a different aspect of natural light behavior. Keep all shadows consistent with a single implied light source direction across the entire page.

Core Principles

Consistent Light Source

Every shadow on the page should share the same ratio between horizontal and vertical offsets. A common convention is a light source above and slightly to the left, meaning vertical offset is roughly 2x the horizontal offset.

Elevation Model

As elements “rise” toward the viewer, three properties change:

  • Offset increases — the shadow moves further from the element
  • Blur expands — the shadow becomes softer and more diffused
  • Opacity decreases — the shadow fades as the element lifts higher

Color-Matched Shadows

Avoid pure black shadows (rgba(0, 0, 0, ...)). Instead, match the hue of the background at low saturation. This prevents the washed-out, desaturated appearance that black shadows cause.

Code Examples

Basic Layered Shadow

.card {
  box-shadow:
    0 1px 1px hsl(0deg 0% 0% / 0.075),
    0 2px 2px hsl(0deg 0% 0% / 0.075),
    0 4px 4px hsl(0deg 0% 0% / 0.075),
    0 8px 8px hsl(0deg 0% 0% / 0.075),
    0 16px 16px hsl(0deg 0% 0% / 0.075);
}

Each layer doubles the previous offset and blur. The cumulative effect is a smooth, natural-looking shadow with depth.

Elevation Levels

/* Low elevation — resting on surface */
.elevation-1 {
  box-shadow:
    0 1px 1px hsl(220deg 60% 50% / 0.07),
    0 2px 2px hsl(220deg 60% 50% / 0.07),
    0 4px 4px hsl(220deg 60% 50% / 0.07);
}

/* Medium elevation — card hover */
.elevation-2 {
  box-shadow:
    0 1px 1px hsl(220deg 60% 50% / 0.06),
    0 2px 2px hsl(220deg 60% 50% / 0.06),
    0 4px 4px hsl(220deg 60% 50% / 0.06),
    0 8px 8px hsl(220deg 60% 50% / 0.06),
    0 16px 16px hsl(220deg 60% 50% / 0.06);
}

/* High elevation — modal / dialog */
.elevation-3 {
  box-shadow:
    0 1px 1px hsl(220deg 60% 50% / 0.05),
    0 2px 2px hsl(220deg 60% 50% / 0.05),
    0 4px 4px hsl(220deg 60% 50% / 0.05),
    0 8px 8px hsl(220deg 60% 50% / 0.05),
    0 16px 16px hsl(220deg 60% 50% / 0.05),
    0 32px 32px hsl(220deg 60% 50% / 0.05);
}

Color-Matched Shadows on Colored Backgrounds

/* On a blue-tinted background */
.card-on-blue {
  background: hsl(220deg 80% 98%);
  box-shadow:
    0 1px 2px hsl(220deg 60% 50% / 0.1),
    0 3px 6px hsl(220deg 60% 50% / 0.08),
    0 8px 16px hsl(220deg 60% 50% / 0.06);
}

/* On a warm background */
.card-on-warm {
  background: hsl(30deg 80% 98%);
  box-shadow:
    0 1px 2px hsl(30deg 40% 40% / 0.1),
    0 3px 6px hsl(30deg 40% 40% / 0.08),
    0 8px 16px hsl(30deg 40% 40% / 0.06);
}

Sharp + Diffuse Combination

/* Tight contact shadow + wide ambient shadow */
.card-sharp-diffuse {
  box-shadow:
    0 1px 3px hsl(0deg 0% 0% / 0.12),
    0 8px 24px hsl(0deg 0% 0% / 0.06);
}

Complete Card Example

<div class="shadow-card">
  <h3>Card Title</h3>
  <p>Card content goes here.</p>
</div>
.shadow-card {
  padding: 24px;
  border-radius: 8px;
  background: white;
  box-shadow:
    0 0.5px 1px hsl(220deg 60% 50% / 0.06),
    0 1px 2px hsl(220deg 60% 50% / 0.06),
    0 2px 4px hsl(220deg 60% 50% / 0.06),
    0 4px 8px hsl(220deg 60% 50% / 0.06),
    0 8px 16px hsl(220deg 60% 50% / 0.06);
  transition: box-shadow 0.3s ease;
}

.shadow-card:hover {
  box-shadow:
    0 1px 2px hsl(220deg 60% 50% / 0.05),
    0 2px 4px hsl(220deg 60% 50% / 0.05),
    0 4px 8px hsl(220deg 60% 50% / 0.05),
    0 8px 16px hsl(220deg 60% 50% / 0.05),
    0 16px 32px hsl(220deg 60% 50% / 0.05),
    0 32px 64px hsl(220deg 60% 50% / 0.05);
}

Live Preview

Flat Shadow vs Layered Shadow

Common AI Mistakes

  • Single flat shadow — Using box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) everywhere. This produces a uniform, artificial look that lacks depth.
  • Pure black shadow colorrgba(0, 0, 0, ...) desaturates the area beneath the shadow, creating a gray, washed-out appearance over colored backgrounds.
  • Inconsistent light direction — Generating different offset angles for different elements, breaking the illusion of a unified light source.
  • Same shadow for all elevations — Using the same shadow for cards, modals, dropdowns, and tooltips, when each should have a distinct elevation level.
  • Overly dark shadows — Setting high opacity values (0.2-0.5) for a single shadow instead of distributing lower opacities across multiple layers.

When to Use

  • Cards and raised surfaces that need to feel physically present
  • Elevation systems where multiple UI layers overlap (cards, dropdowns, modals, tooltips)
  • Hover states that should make an element appear to lift off the page
  • Any element that benefits from a sense of depth without feeling artificially heavy

References

Revision History