Quick answer
The CSS box-shadow property draws one or more shadows around an element: box-shadow: x-offset y-offset blur spread color, with an optional inset keyword and commas between layers. Several soft layers look far more natural than one big blur. In Playxoft's free Box Shadow Generator, the Smooth tab builds eased layers from a single elevation value, or you can edit each layer by hand, then copy the CSS, Tailwind class or Sass.
- Layered shadows
- Smooth elevation slider
- Material elevations 0 to 24
- Box, drop and text shadows
- Neumorphic presets
- Paste existing CSS to edit
- CSS, Tailwind and Sass
- Undo, redo and share links
How to use the Box Shadow Generator
- 1Pick Box shadow, Drop shadow or Text shadow in the toolbar.
- 2Start from a Preset, or open Smooth and drag Elevation to generate layered shadows from one value.
- 3Fine-tune in Layers: drag the offset pad, then set Blur, Spread, Shadow color and Inset for the selected layer.
- 4Check the result on light, dark and your own page color with the background buttons above the preview.
- 5To tweak a shadow you already use, paste it into Paste existing CSS; box-shadow, text-shadow and drop-shadow() are all understood.
- 6Copy the CSS, Tailwind or SCSS output, or press Share to copy a link to the design.
What is the CSS box-shadow syntax?
Each shadow is a list of lengths and a color, and an element can have as many shadows as you like, separated by commas. The first shadow in the list paints on top.
box-shadow: [inset] <offset-x> <offset-y> [<blur>] [<spread>] <color>;
box-shadow: 0 4px 12px -2px rgb(15 23 42 / 18%);| Value | Default | What it does |
|---|---|---|
inset | off | Draws the shadow inside the border box, for pressed or carved looks |
| offset-x | required | Moves the shadow right (positive) or left (negative) |
| offset-y | required | Moves it down (positive) or up (negative) |
| blur | 0 | Softens the edge; it cannot be negative |
| spread | 0 | Grows or shrinks the shadow before blurring |
| color | currentColor | Any CSS color; use transparency so the background shows through |
A shadow follows the element's border-radius, does not take up layout space and does not catch clicks. It is clipped by any ancestor with overflow: hidden and by clip-path, which is the usual reason a shadow seems "cut off".
Why do layered shadows look more realistic?
Real shadows have a small, dark core where an object nearly touches a surface and a wide, faint penumbra around it. A single large blur gets one of those right and the other wrong: it either looks muddy or floats with no contact. Stacking layers whose offset and blur grow while each layer stays faint reproduces both.
box-shadow:
0 1px 1px rgb(0 0 0 / 7%),
0 2px 2px rgb(0 0 0 / 7%),
0 4px 4px rgb(0 0 0 / 7%),
0 8px 8px rgb(0 0 0 / 7%),
0 16px 16px rgb(0 0 0 / 7%);The Smooth tab automates this. Elevation sets the outermost offset, an easing curve spaces the inner layers (ease in keeps them tight, doubling gives 1, 2, 4, 8 and 16px), and every layer gets the same opacity a, chosen so that where all n layers overlap the result equals your total: 1 − (1 − a)^n. Tinting the shadow toward a deep slate or navy instead of pure black also makes it feel lit rather than dirty.
How should shadows work in dark mode?
A dark shadow on a near-black page has almost nothing to darken, so elevation that reads clearly in light mode disappears. Three techniques work better:
- Lighter surfaces for higher elements. Raise a card by making its background a few steps lighter than the page. Material Design's dark theme expresses elevation this way.
- A faint light edge. A 1px border or
0 0 0 1px rgb(255 255 255 / 8%)ring separates surfaces without any blur. - Glows instead of shade. Colored, zero-offset shadows read as light on dark backgrounds (see the Neon glow preset).
.card { box-shadow: 0 8px 24px -6px rgb(15 23 42 / 20%); }
@media (prefers-color-scheme: dark) {
.card { box-shadow: 0 0 0 1px rgb(255 255 255 / 8%), 0 8px 24px -6px rgb(0 0 0 / 60%); }
}Use the Dark and custom background buttons above the preview to check both themes before you copy.
box-shadow vs drop-shadow() vs text-shadow: which should I use?
box-shadow | filter: drop-shadow() | text-shadow | |
|---|---|---|---|
| Follows | The element's box and border radius | The actual painted shape, including transparency | Each glyph |
| Spread | Yes | No | No |
| Inset | Yes | No | No |
| Multiple shadows | Comma-separated | Chain several drop-shadow() functions | Comma-separated |
| Typical use | Cards, buttons, modals | Icons, transparent PNGs, SVGs, odd shapes | Headlines, glows, legibility over images |
drop-shadow() is the only one that hugs a non-rectangular shape, but filter creates a stacking context and becomes the containing block for position: fixed children. An element with clip-path clips its own drop shadow, so put the filter on a wrapper (pair it with the clip-path generator).
Are box shadows bad for performance?
Static shadows are cheap, even with several layers. The cost comes from very large blur radii over big areas and, above all, from animating box-shadow, which repaints the element on every frame. For hover effects, put the larger shadow on a pseudo-element and animate its opacity, which the compositor handles without repainting:
.card { position: relative; box-shadow: 0 1px 3px rgb(0 0 0 / 10%); }
.card::after {
content: ""; position: absolute; inset: 0; border-radius: inherit;
box-shadow: 0 16px 40px -8px rgb(0 0 0 / 25%);
opacity: 0; transition: opacity 200ms ease;
}
.card:hover::after { opacity: 1; }For glassy panels that combine a shadow with a blurred backdrop, see the glassmorphism generator.
Frequently asked questions
Last updated by the Playxoft engineering team.