Dev ToolsApril 12, 2026

CSS Box Shadow Guide: Syntax, Layering & Design Techniques

By The hakaru Team·Last updated March 2026

Quick Answer

  • *Syntax: box-shadow: offset-x offset-y blur spread color.
  • *Layer multiple shadows (comma-separated) for realistic depth.
  • *inset keyword creates inner shadows. Omit for outer shadows.
  • *Use rgba() with low opacity for subtle, natural-looking shadows.

The Box-Shadow Syntax

Every box-shadow needs at minimum two values: horizontal and vertical offset. Add optional blur radius, spread radius, and color for control.

box-shadow: [inset] offset-x offset-y [blur] [spread] color;

offset-x: Positive = right, negative = left. offset-y: Positive = down, negative = up. blur: 0 = sharp edge, higher = softer. spread: Positive = larger shadow, negative = smaller. inset: Makes the shadow appear inside the element.

Layered Shadows for Realism

Real shadows aren’t uniform. A single box-shadow looks flat and artificial. Layering multiple shadows with progressive values creates the illusion of realistic depth. This technique was popularized by Material Design and refined by design systems like Tailwind CSS.

The principle: start with a tight, dark shadow close to the element (contact shadow) and add increasingly diffuse, lighter shadows at greater offsets (ambient shadow). Each layer uses low opacity so they blend naturally.

Example card shadow with 4 layers:

box-shadow:
  0 1px 2px rgba(0,0,0,0.04),
  0 2px 4px rgba(0,0,0,0.04),
  0 4px 8px rgba(0,0,0,0.04),
  0 8px 16px rgba(0,0,0,0.04);

Common Shadow Patterns

PatternCSSUse Case
Subtle card0 1px 3px rgba(0,0,0,0.12)Cards, panels
Elevated card0 4px 12px rgba(0,0,0,0.15)Modals, hover states
Bottom only0 4px 6px -2px rgba(0,0,0,0.1)Headers, navbars
All sides glow0 0 20px rgba(59,130,246,0.5)Focus rings, highlights
Hard shadow4px 4px 0 #000Retro, brutalist style

Inset Shadows

The inset keyword flips the shadow to the inside of the element. This creates pressed or recessed effects. Common uses: text input fields, toggle buttons in “active” state, and neumorphism pressed states.

box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);

Combine inset and outer shadows for rich effects. A button might have an outer shadow in its default state and switch to inset on click.

Neumorphism

Neumorphism creates a soft, extruded look using two shadows on elements that match their parent’s background color. One shadow is lighter (simulating light source), the other darker (simulating shadow). The element blends into the surface rather than floating above it.

The approach has accessibility concerns — low contrast between elements makes interfaces harder to parse. Use it sparingly and ensure interactive elements have additional visual indicators like borders or color changes.

Performance Considerations

Box shadows trigger repaint but not reflow, so they’re less expensive than you might expect. However, large blur radii on many elements (especially during scrolling or animation) can cause jank on mobile devices.

For animated shadows (hover transitions), consider animating opacity on a pseudo-element instead. Create the shadow on a ::after pseudo-element positioned behind the card and transition its opacity from 0 to 1. This is GPU-accelerated and smoother than transitioning box-shadow directly.

Design and preview box shadows visually

Use our free Box Shadow Generator →

Frequently Asked Questions

What is the CSS box-shadow syntax?

box-shadow: [inset] offset-x offset-y [blur] [spread] color. Only offsets are required. Multiple shadows are comma-separated.

How do I create a realistic shadow?

Layer multiple shadows with increasing offsets and blur, each at low opacity. This mimics how real shadows work: tight contact shadow plus diffuse ambient shadow.

What’s the difference between box-shadow and drop-shadow?

box-shadow follows the element’s box shape. filter: drop-shadow() traces the actual content shape including transparent regions. box-shadow supports inset and spread; drop-shadow does not.

Does box-shadow affect performance?

Triggers repaint but not layout. Large blur on many elements can cause jank on mobile. For animations, use pseudo-element opacity transitions instead.

How do I create neumorphism?

Two shadows on an element matching parent background: light shadow upper-left, dark shadow lower-right. Add inset to both for pressed state. Mind accessibility — low contrast can be hard to read.