How do you use this tool?
- Edit per-layer parameters — offset, blur, spread, colour, inset toggle.
- Add more layers or click a Material elevation step (1–24) to load a canonical stack.
- 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 actualborder— the box isn’t eaten bybox-sizingcalculations.
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:
- 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. - 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.
- 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.
Which related CSS tools are useful?
More tools for CSS authoring and colour work:
- CSS Gradient Generator — Build linear, radial, and conic gradients in OKLCH / Tailwind v4.
- Hex to RGB converter — Convert hex codes to RGB, HSL, and OKLCH.
- Contrast checker — Verify WCAG AAA contrast between two colours.
- CSS Formatter — Pretty-print or minify raw CSS.
Last updated: