Skip to content
Runs local · no upload

Build box-shadow stacks with multi-layer control

One layer feels flat. Three stacked layers behave like real light.

Preview
Auto-layered recipe
Elevation
Light direction
Tint colour
Material elevation

Click a step to load the canonical Material 3 shadow stack.

Shadow layers 2 / 10
  • Layer 1
  • Layer 2
Output OKLCH
Colour space
box-shadow: 0px 4px 8px -2px oklch(0.00% 0.000 0 / 0.078), 0px 12px 24px -6px oklch(0.00% 0.000 0 / 0.078);
Presets

How It Works

  1. 01

    Paste text or code

    Paste your content into the input field or type directly.

  2. 02

    Instant processing

    The tool processes your content immediately and shows the result.

  3. 03

    Copy result

    Copy the result to your clipboard with one click.

Privacy

All calculations run directly in your browser. No data is sent to any server.

X/Y offset, blur, spread, colour, and inset — per shadow layer. Stack up to ten layers, load any Material Design elevation step in one click, or generate ambient + key + contact shadows with the auto-layered recipe. Output as CSS, Tailwind v4, or design token. Runs in the browser, no account.

Shadow layers
10
Output formats
4
Material steps
9
01 — How to Use

How do you use this tool?

  1. Edit per-layer parameters — offset, blur, spread, colour, inset toggle.
  2. Add more layers or click a Material elevation step (1–24) to load a canonical stack.
  3. Copy the output as plain CSS, a Tailwind v4 utility with `@theme` block, or a CSS custom-properties set.

What does the box-shadow generator do?

The generator builds CSS shadows visually. Per layer you set the horizontal and vertical offset, the blur radius, the spread, and the shadow colour — plus an inset toggle that flips between outer and inner shadows. Up to ten layers can be stacked, which is non-negotiable for realistic UI shadows: a single layer reads flat, three stacked layers mimic how light actually behaves in a room.

The live preview renders the result on a card whose background colour you pick — important, because the same shadow set lands very differently on warm off-white and on dark-mode grey. Output ships in four formats: plain CSS for classic stylesheets, a Tailwind v4 class paired with a @theme block so projects can register the stack as a design token, an inline-style attribute, and a CSS custom-properties block that exports each stack as a reusable token.

How does the box-shadow property work?

The CSS box-shadow property follows a simple syntax: [inset] offset-x offset-y [blur] [spread] color. A classic card shadow looks like this: box-shadow: 0 4px 8px -2px rgba(0,0,0,0.1). Positive Y values push the shadow downward, positive X values to the right. Blur softens the edge — at 0 px the shadow is razor-sharp, at 40 px it diffuses like a cloud.

Spread grows or shrinks the shadow relative to the element. A negative spread tucks the shadow closer to the box, which is the modal-lift trick — the shadow doesn’t bleed wider than the element. Positive spread expands it — useful for glow effects or wide highlight halos in dark-mode designs.

How do you combine multiple box-shadows?

Multiple shadows belong in a single box-shadow declaration, separated by commas. Order matters. The first entry renders on top — if you want a sharp outline shadow over a soft ambient layer, the outline entry comes first.

.card {
  box-shadow:
    0 1px 2px rgba(0,0,0,0.08),   /* contact */
    0 4px 8px rgba(0,0,0,0.08),   /* key */
    0 12px 24px rgba(0,0,0,0.08); /* ambient */
}

Three layers usually do the job. Realistic UI shadows from Material Design stack exactly these three: a short, dense contact shadow at the bottom edge, a medium key shadow as the main accent, and a wide soft ambient shadow simulating room light bouncing off the surface. The generator’s auto-recipe mode builds this stack in one click.

What does inset mean and when do you use it?

The inset keyword in front of the values flips the shadow inward — the element looks pressed into the surface. The browser paints inset shadows above the background but under the content. Common use cases:

  • Form inputs. A soft inset at the top edge (inset 0 1px 2px rgba(0,0,0,0.05)) signals “you can drop content in here”.
  • Pressed buttons. A deeper inset (inset 0 2px 4px rgba(0,0,0,0.16)) gives the classic active state without the element shifting position.
  • Hairline outlines. inset 0 0 0 1px var(--color-border) produces a pixel-perfect inner line that renders cleaner on High-DPI browsers than an actual border — the box isn’t eaten by box-sizing calculations.

A checkbox per layer switches between inset and outset. They mix freely in the same stack — a classic card look pairs an outer ambient shadow with an inner hairline.

How do you pick colour and alpha for realistic shadows?

Pure black at fixed alpha (rgba(0,0,0,0.2)) often reads harder than necessary. Three strategies:

  1. Tint to the background. When the page sits on warm off-white (#FAFAF9), warm-tinted shadows (oklch(0.2 0.05 60 / 0.2)) feel more natural than pure black. The generator takes any tint colour and folds the right alpha into each layer.
  2. Per-layer alpha, not single-layer alpha. Three stacked shadows at 8%, 12%, and 20% alpha (Comeau’s recipe) produce more depth than a single shadow at 40% alpha. Eyes read the stepped light curve as physically correct.
  3. OKLCH for hue-stable colour. OKLCH (CSS Color Module Level 4) keeps chroma constant across lightnesses. Tinting a shadow toward a brand colour, OKLCH preserves saturation in the dark range — hex/RGBA loses it.

The generator emits the colour in the chosen notation per output format: hex for maximum compatibility, HSL for intuitive hue/sat/light control, OKLCH for Tailwind v4 workflows.

When does Material Design elevation help?

Material Design defines elevation levels 1–24 as canonical steps, each with a precisely staged shadow stack. For a Material 3 look, load step 1 for resting cards, step 4 for floating action buttons, step 8 for modal sheets, and step 24 for top-layer dialogs. The generator surfaces 9 canonical levels (1, 2, 3, 4, 6, 8, 12, 16, 24) as quick-picks.

For designs outside the Material ecosystem the levels still work as starting points: load step 4, pull blur values down, swap the black tint for a brand hue. The output updates live. You get the correctly-staged 3-layer structure without deriving it by hand.

How do you ship box-shadows as design tokens?

Instead of declaring every card shadow inline, register it once as a custom property:

:root {
  --shadow-card: 0 1px 2px rgba(0,0,0,0.08), 0 4px 8px -2px rgba(0,0,0,0.08);
  --shadow-modal: 0 8px 16px -4px rgba(0,0,0,0.16), 0 20px 40px -8px rgba(0,0,0,0.12);
}

.card { box-shadow: var(--shadow-card); }
.modal { box-shadow: var(--shadow-modal); }

Tailwind v4’s CSS-first config allows the same pattern straight in the @theme block:

@theme {
  --shadow-card: 0 1px 2px rgba(0,0,0,0.08), 0 4px 8px -2px rgba(0,0,0,0.08);
}

That automatically exposes a shadow-card utility — just like a built-in class. The generator outputs both variants in the “CSS variables” and “Tailwind v4” modes, each with a configurable token name.

What is the runtime cost of box-shadows?

Browsers paint each shadow over a separate paint pass: the element first, then each shadow from back to front. Three factors drive cost:

  • Blur radius. Large blur values (> 40 px) force the GPU into large convolution operations per frame. On static cards it doesn’t matter — on animated hover states or scroll-driven lifts it eats frame budget.
  • Layer count. Four or more shadows in a declaration roughly double per-frame paint work. Three layers is the usual maximum for animated UI.
  • Spread values. Larger spread expands the paint region and the total pixel count the browser must blur.

The generator surfaces a performance hint when blur > 40 px OR layer count > 3. The suggested fix in both cases: set will-change: box-shadow during the animation and clear it afterwards — this pins the shadow to its own compositor layer, making recomposition cheaper. Never leave it on permanently; it consumes memory.

What are the use cases?

Resting cards. A subtle 2-layer stack is plenty. Example: 0 1px 2px rgba(0,0,0,0.08), 0 4px 8px -2px rgba(0,0,0,0.08).

Hover lifts. Same stack, Y offset and blur roughly 2× — reads as a clean lift.

Modal sheets. Bigger Y offset, higher blur, negative spread so the shadow stays tight around the box. Plus an outline layer for High-Contrast Mode.

Inset form fields. Single inset layer at the top edge for the “drop content here” vibe.

Glow states. Spread > 0 with low alpha and a brand hue — useful for focus rings on dark backgrounds.

Soft-UI accents. A double shadow with a light highlight (top-left) plus a dark shadow (bottom-right) — there’s a preset for it.

What do users ask most often?

How does the CSS box-shadow property work?

The property paints shadows around an element box. You set a horizontal and vertical offset, optionally blur and spread, then the colour. Multiple shadows separated by commas stack — the first entry sits on top, later entries render behind.

How do you combine multiple box-shadows?

Multiple shadows belong in a single box-shadow declaration, separated by commas. Order matters: the first entry renders on top. The generator lets you stack up to ten layers — the preview updates instantly, and the output preserves layer order in the CSS.

What does inset mean in a box-shadow?

The inset keyword flips the shadow inward instead of outward — the element looks pressed into the surface. Inset shadows paint over the background but under the content. A toggle in the generator switches each layer between inset and outset.

What blur value works for card shadows?

Subtle cards use 4–8 px blur, hover lifts 12–24 px, modal lifts 24–40 px. Higher blur reads softer but costs paint time on mobile. The generator warns when blur exceeds 40 px and suggests will-change: box-shadow for animations.

How do I use box-shadows in Tailwind v4?

Tailwind v4 accepts arbitrary shadow-[…] classes for any shadow value. Cleaner pattern: register the stack via @theme { --shadow-app: …; } in your CSS and use the shadow-app class like a built-in utility. The generator emits both variants.

What is an auto-layered shadow?

Three stacked layers — a short contact shadow at the bottom edge, a medium key shadow as the main accent, and a long soft ambient shadow for depth — produce far more realistic results than a single layer. The auto-recipe mode builds this 3-layer stack from an elevation step, light angle, and tint colour.

Does OKLCH work in box-shadow colours?

Yes. Browsers that support OKLCH (Chrome 111+, Firefox 113+, Safari 16.4+) render oklch(0.6 0.18 30 / 0.2) as a shadow colour the same way they accept any hex value. OKLCH keeps chroma stable when tinting — the generator switches between hex, HSL, and OKLCH output without loss.

Does the tool save my shadow sets?

No. Every input stays in the browser tab — nothing is stored or uploaded. Reloading clears the editor. To save a set, copy the CSS variables output into your own stylesheet or your tokens.css.

More tools for CSS authoring and colour work:

Last updated:

You might also like