CSS box-shadow generator
Stack multiple box-shadow layers with live x, y, blur, spread, colour and inset controls, preview them on a real card, and copy the CSS or Tailwind class.
- Runs in your browser
- Nothing you enter is sent
- Free, no account
Tinting the shadow with a dark version of the background reads far better than pure black.
Draws the shadow inside the box instead of behind it — the standard way to make an input look recessed.
Tinting the shadow with a dark version of the background reads far better than pure black.
Draws the shadow inside the box instead of behind it — the standard way to make an input look recessed.
box-shadow: 0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1);
Tailwind — exact arbitrary value
shadow-[0px_4px_6px_-1px_rgba(0,0,0,0.1),0px_2px_4px_-2px_rgba(0,0,0,0.1)]
Tailwind — closest built-in
shadow-md
An exact match for the stock scale.
Layer breakdown
| # | X | Y | Blur | Spread | Colour |
|---|---|---|---|---|---|
| 1 | 0 | 4 | 6 | -1 | rgba(0, 0, 0, 0.1) |
| 2 | 0 | 2 | 4 | -2 | rgba(0, 0, 0, 0.1) |
How to build a shadow
- Start with the two default layers — a tight contact shadow and a wider ambient one — and adjust from there.
- Move the vertical offset first. It decides how high the element appears to float.
- Set the blur to roughly one and a half times the vertical offset for a natural look.
- Pull the spread negative to tuck the shadow behind the element so it only peeks out at the bottom.
- Tint the colour towards the background hue and keep opacity low. Copy the CSS, or the matching Tailwind class.
What the five values do
| Value | Effect | Typical range |
|---|---|---|
| Horizontal offset | Moves the shadow left or right. Implies a light source to one side. | 0 — real UI light comes from above |
| Vertical offset | Moves the shadow down. The main cue for how high the element sits. | 1–25 px |
| Blur radius | Softens the edge. Zero gives a hard-edged duplicate shape. | 1.5× the vertical offset |
| Spread | Grows or shrinks the shadow shape before blurring. | −12 to 0 px |
| Colour | Any CSS colour, almost always with low alpha. | 5–25% opacity |
inset | Draws the shadow inside the border box instead of outside. | Recessed inputs, wells, pressed states |
The order in the declaration is x y blur spread colour, with inset
optionally first. Blur and spread may both be omitted, so 0 1px #0002 is a valid
one-pixel hairline shadow.
Why one layer never looks right
Under real light an object casts two distinguishable shadows: a small, relatively dark
contact shadow immediately beneath it where light is fully blocked, and a large, very
faint ambient shadow spreading outwards from bounced light. A single CSS layer can only
be one or the other, which is why a lone 0 4px 8px rgba(0,0,0,.2) reads as a grey
smear rather than as depth.
Every serious elevation scale stacks at least two layers. Tailwind’s shadow-md, for
example, is a 6 px blur with −1 px spread over a 4 px blur with −2 px spread; Material Design
uses three. Add layers in this tool and you can see the difference immediately on the sample
card.
Tailwind’s elevation scale, spelled out
| Class | Value |
|---|---|
shadow-2xs | 0 1px rgb(0 0 0 / 0.05) |
shadow-xs | 0 1px 2px 0 rgb(0 0 0 / 0.05) |
shadow-sm | 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) |
shadow-md | 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) |
shadow-lg | 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1) |
shadow-xl | 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1) |
shadow-2xl | 0 25px 50px -12px rgb(0 0 0 / 0.25) |
inset-shadow-sm | inset 0 2px 4px 0 rgb(0 0 0 / 0.05) |
The “closest built-in” readout compares your first layer against these and tells you how far off it is. If the difference is small, using the stock class keeps your project consistent; if it matters, the arbitrary-value class above it reproduces your shadow exactly.
Shadows in dark mode
A black shadow on a dark background is nearly invisible, which is why simply reusing a light-mode elevation scale makes dark interfaces look flat. Three approaches that work:
- Raise the surface instead. Material’s dark theme lightens the card background as elevation increases rather than darkening what is under it.
- Increase the opacity substantially — often to 40–60% — and rely on a larger blur.
- Add a top inset highlight such as
inset 0 1px 0 rgb(255 255 255 / 0.06), which reads as a lit edge and separates the card from the background far more effectively than a shadow does.
box-shadow versus filter: drop-shadow()
box-shadow | filter: drop-shadow() | |
|---|---|---|
| Follows | The border box, including border-radius | The rendered alpha channel |
| Transparent PNGs and SVGs | Rectangular shadow around the whole box | Shadow hugs the actual artwork |
| Multiple layers | Comma-separated in one declaration | Chain several drop-shadow() functions |
| Spread parameter | Yes | No |
inset | Yes | No |
| Cost | Cheap when static | More expensive; creates a containing block |
Performance
A static shadow costs almost nothing. Animating one is a different story: the browser has to
recompute the blur on every frame, on the main thread, for the full painted area. If a card
should lift on hover, do not transition box-shadow. Put the larger shadow on an
absolutely positioned pseudo-element with opacity: 0 and transition the opacity
instead — that runs on the compositor and stays smooth even on a mid-range phone.
Questions
Why do professional shadows use more than one layer?
Real light produces both a tight contact shadow directly under an object and a wide, faint ambient shadow around it. One layer can only be one of those, which is why single-layer shadows look like a grey smudge. Every serious design system — Material, Tailwind, Apple’s — stacks at least two.
What does spread actually do?
It grows or shrinks the shadow shape before the blur is applied. A negative spread pulls the shadow in so it peeks out only at the bottom, which is the trick behind the tidy look of Tailwind’s md and lg shadows.
Should the shadow be black?
Rarely. Pure black at low opacity turns everything under it grey and slightly dead. Use a very dark, desaturated version of the background hue — a dark navy on a blue-grey page — and the shadow reads as depth instead of dirt.
Is box-shadow expensive to render?
A static shadow is cheap. Animating one is not, because the browser repaints the blur on every frame. If you need a shadow to grow on hover, animate the opacity of a second pseudo-element that already carries the larger shadow instead.
What is the difference between box-shadow and drop-shadow?
box-shadow always follows the border box, so a transparent PNG gets a rectangular shadow. The filter: drop-shadow() function follows the actual alpha channel, which is what you want for logos, icons and irregular shapes.