CSS Box Shadow Generator
Drag the offset, blur and spread of each shadow layer, stack as many layers as you need, or build a smooth multi-layer shadow from one light direction. See how far it reaches and how it looks on your page colour, then copy the CSS or Tailwind class.
Preview
- Paints about 10px above, 18px right, 26px below and 18px left of the box. A parent with overflow: hidden needs at least that much padding or the shadow is cut off.
- Where every layer overlaps, the page goes from #F1F5F9 to #BEC3CA, a 1.62:1 difference.
.card {
box-shadow:
0 1px 2px rgb(15 23 42 / 0.08),
0 8px 24px -6px rgb(15 23 42 / 0.16);
}Reading a box-shadow value
Each shadow is two to four lengths, a colour and an optional inset. The lengths must stay together and in order; the colour and inset can go before or after them. 0 8px 24px -6px rgb(15 23 42 / 0.16) reads as: no sideways shift, 8px down, a 24px blur, pulled in by 6px, slate at 16% opacity.
| Part | If left out | Negative values | What it does |
|---|---|---|---|
| X offset | Required | Yes, moves left | Shifts the shadow right (positive) or left |
| Y offset | Required | Yes, moves up | Shifts the shadow down (positive) or up |
| Blur radius | 0 (hard edge) | Not allowed | Softens the edge; the fade is about twice the blur wide, centred on the edge |
| Spread | 0 | Yes, shrinks it | Grows or shrinks the shadow shape before it is blurred |
| Colour | currentcolor (the text colour) | — | Any CSS colour; the transparency is what keeps it soft |
| inset | Outer shadow | — | Draws the shadow inside the box instead of behind it |
Commas separate layers, and the first layer is drawn on top. Unprefixed box-shadow has worked since Chrome 10, Firefox 4 and Safari 5.1 (iOS 5), with spread and inset included, so the -webkit-box-shadow line older generators still add is no longer needed.
How far a shadow reaches past the box
The specification defines blur as a Gaussian blur with a standard deviation of half the blur radius, which makes the fade about twice the blur wide, centred on the shadow's edge. So an outer shadow paints roughly spread + blur past the box, plus the offset on the side it moves towards and minus it on the other:
| Side | Working | Reach |
|---|---|---|
| Top | −6 + 24 − 8 | 10px |
| Right | −6 + 24 + 0 | 18px |
| Bottom | −6 + 24 + 8 | 26px |
| Left | −6 + 24 − 0 | 18px |
Tick "Show how far it reaches" to see this as a dashed outline. It matters because shadows take no space in the layout and do not add to the scrollable area, so a parent with overflow: hidden, auto or clip cuts them off in a straight line. Give that parent padding at least as large as the reach, or move the clipping elsewhere.
Spread also changes the shadow's corners. With a positive spread, the corner radius grows by the spread, so 12px rounding and 10px spread give a 22px shadow corner. When the rounding is smaller than the spread, the browser adds less so small corners stay crisp: 10px rounding with 20px spread gives 27.5px, not 30px, and square corners stay square.
Stacking layers for a smoother shadow
One blurred shadow has a single, even fade. Real shadows are dark and sharp close to the object and fade out wide, and you get much closer to that by stacking several layers, each with double the offset and blur of the last. "Smooth shadow" builds exactly that.
Stacked transparent layers darken each other: two 20% layers make 1 − 0.8 × 0.8 = 36%, not 40%. To land on a chosen darkness D with n layers, each one needs an opacity of 1 − (1 − D)1/n.
| Layers | For 20% total | For 30% total |
|---|---|---|
| 1 | 0.200 | 0.300 |
| 2 | 0.106 | 0.163 |
| 3 | 0.072 | 0.112 |
| 4 | 0.054 | 0.085 |
| 5 | 0.044 | 0.069 |
| 6 | 0.037 | 0.058 |
| 8 | 0.028 | 0.044 |
The Smooth preset is five layers ending at 32px down with 64px blur and 20% darkness, which works out to 4.4% each:
0 2px 4px rgb(15 23 42 / 0.044),
0 4px 8px rgb(15 23 42 / 0.044),
0 8px 16px rgb(15 23 42 / 0.044),
0 16px 32px rgb(15 23 42 / 0.044),
0 32px 64px rgb(15 23 42 / 0.044)Keep one light direction for the whole page. If every shadow falls downward, an element whose shadow falls to the side looks misplaced, even to people who could not say why.
Inset shadows
inset makes the box look cut into the page. The shadow is painted just above the element's background but below its border and content, and only inside the padding box, so it starts at the inner edge of any border. Spread works in reverse: a larger spread makes the shadowed band wider and leaves less of the middle clear.
- Wells and fields:
inset 0 2px 4px rgb(15 23 42 / 0.12)(the Inset well preset) darkens the top edge as if light came from above. - Pressed buttons: switch from an outer shadow to a small inset one in
:active. - A line that takes no space:
inset 0 0 0 1pxwith a colour draws a 1px edge inside the box without changing its size, and it can sit next to an outer shadow in the same list.
A child with its own background covers an inset shadow, because the shadow sits under the content. Put the shadow on the child, or add the inset on a ::after overlay with pointer-events: none.
Shadows on dark backgrounds
A shadow can only darken what is behind it, and a dark page has little room left. The same black shadow at 25% opacity takes white to #BFBFBF, a 1.83:1 difference, but takes #0F172A only to #0B1120, 1.05:1, which hardly shows. The line under the preview runs this check for your page colour.
On dark themes, elevation usually comes from somewhere else:
- Make raised surfaces lighter than the page (the Glow preset puts a
#1E293Bbox on a#0F172Apage). - Add a faint light edge such as
inset 0 1px 0 rgb(255 255 255 / 0.06)along the top. - Use a coloured glow (zero offset, wide blur, a little spread) for something that should look lit rather than lifted.
A shadow tinted toward the page colour, such as navy on a navy page, looks more natural than pure black on any colour except white and grey.
box-shadow or filter: drop-shadow()
| box-shadow | filter: drop-shadow() | |
|---|---|---|
| Shape it follows | The box and its border-radius | The visible pixels, including transparent PNG and SVG shapes |
| Spread | Yes | No |
| Inset | Yes | No |
| Several shadows | Comma-separated list | Chain several drop-shadow() functions |
| Includes child elements and text | No, only the box | Yes, everything inside |
| Visible through a transparent box | No: it is clipped out from under the box | Only where pixels are painted |
Use drop-shadow() for icons, logos, cut-out photos and shapes made with clip-path, where a rectangle would look wrong. Its third length is a standard deviation, not a blur radius, so drop-shadow(0 4px 8px …) is about as soft as box-shadow: 0 4px 16px …; halve the number when moving a shadow to the filter.
Animating a shadow on hover
transition: box-shadow works, but the browser repaints the shadow on every frame, and large blurs on a page full of cards can stutter on slower phones. Changing only opacity and transform avoids repainting, so the usual trick is to put the bigger shadow on a pseudo-element and fade it in:
.card {
position: relative;
box-shadow: 0 1px 2px rgb(15 23 42 / 0.08);
transition: transform 0.2s;
}
.card::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
box-shadow: 0 24px 48px -12px rgb(15 23 42 / 0.35);
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
.card:hover { transform: translateY(-2px); }
.card:hover::after { opacity: 1; }The overlay has no background, and an outer shadow is clipped out from under its own box, so nothing covers the card's content. Wrap the movement in @media (prefers-reduced-motion: no-preference) if it is more than a couple of pixels.
Tailwind's shadow scale
The Tailwind buttons under "Start from" load these values. Each utility is one or two layers of black at 5–25%, which is why they look neutral on any background colour. For anything else, the Tailwind tab writes an arbitrary shadow-[…] class.
| Utility | v3 name | box-shadow value |
|---|---|---|
| shadow-2xs | — | 0 1px rgb(0 0 0 / 0.05) |
| shadow-xs | shadow-sm | 0 1px 2px 0 rgb(0 0 0 / 0.05) |
| shadow-sm | shadow | 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) |
| shadow-md | shadow-md | 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) |
| shadow-lg | shadow-lg | 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1) |
| shadow-xl | shadow-xl | 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1) |
| shadow-2xl | shadow-2xl | 0 25px 50px -12px rgb(0 0 0 / 0.25) |
| inset-shadow-sm | shadow-inner (0 2px 4px 0, 5%) | inset 0 2px 4px rgb(0 0 0 / 0.05) |
When the shadow is cut off or missing
| Symptom | Cause | Fix |
|---|---|---|
| Cut off in a straight line | A parent has overflow hidden, auto or clip | Pad the parent by the reach shown under the preview |
| Hidden behind the next card | Later elements paint over earlier ones | position: relative and a z-index on the shadowed element |
| Cannot see it through a see-through box | Outer shadows are clipped out from under the box itself | Expected; use an inset shadow or a blurred pseudo-element behind |
| Inset shadow vanished | A child with a background covers it | Shadow the child, or use a ::after overlay |
| No shadow on table rows or cells | Outer shadows do nothing on table parts with border-collapse: collapse | Shadow the table or a wrapper, or use border-collapse: separate |
| Odd shadows on wrapped inline text | Each line fragment is shadowed as one long box | box-decoration-break: clone (Safari needs -webkit-) |
| Shadow is the wrong colour | No colour given, so it uses the text colour | Always include a colour |
Frequently asked questions
How do I put a shadow on the bottom only?
Use a negative spread equal to the blur and a Y offset of the same size, for example 0 12px 12px -12px rgb(0 0 0 / 0.4). The spread pulls the shape in so the blur cannot show at the top or sides, and the offset pushes it out below. It is the "Bottom only" preset.
Which layer is on top when there are several?
The first one in the list. Put the small, sharp layer first and the wide, faint one last, though with transparent shadows the order changes the result only slightly.
Can a box-shadow be a gradient?
No, each layer takes one colour. For a gradient glow, put the gradient on a ::before pseudo-element behind the box and blur it with filter: blur().
What is the difference between box-shadow and text-shadow?
text-shadow follows the letter shapes and has no spread or inset. box-shadow shadows the whole box. Both take a comma-separated list with the first shadow on top.
Why does my shadow look grey and muddy?
Usually too much opacity on one big layer. Try two or more layers with lower opacity, and tint the colour toward the background, for example a dark navy instead of black on a blue-grey page.
How is the Soft UI (neumorphism) look made?
A box the same colour as the page, with a darker shadow on one side and a white one on the other, as in the Soft UI preset. The edges have very little contrast, so do not rely on it alone to show where buttons and fields are.
Sources
- W3C: CSS Backgrounds and Borders Module Level 3, box-shadow: syntax, blur as a Gaussian, spread radius rule, painting order, overflow and tables
- MDN: box-shadow: values and browser support
- MDN: drop-shadow(): how the filter differs from box-shadow
- W3C: Filter Effects Module Level 1: drop-shadow() takes a standard deviation, not a blur radius, and has no spread
- MDN: box-decoration-break: shadows on wrapped inline elements
- web.dev: How to create high-performance CSS animations: why transform and opacity animate more smoothly than paint properties
- Tailwind CSS: box-shadow: utility names and arbitrary values
- Josh W. Comeau: Designing Beautiful Shadows in CSS: layered shadows and a consistent light source
Related Tools
Build and preview common CSS Grid layout patterns.
Build linear and radial gradients with custom color stops.
Remove, replace, and export image metadata.
Generate and inspect solid background-color declarations.
Generate gradient and image background-image CSS.
Generate uniform or side-specific CSS border declarations.