Syntax
box-shadow: [inset] <x> <y> [blur] [spread] <color>;
.card { box-shadow: 0 1px 3px rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
.button:focus-visible { box-shadow: 0 0 0 3px rgb(59 130 246 / 0.5); } /* focus ring */
.well { box-shadow: inset 0 2px 4px rgb(0 0 0 / 0.06); }
Smooth layered shadow
Five layers with doubling distance and blur at 6% opacity each, from the “Layered (smooth)” preset:
box-shadow: 0 1px 2px rgb(15 23 42 / 0.06), 0 2px 4px rgb(15 23 42 / 0.06), 0 4px 8px rgb(15 23 42 / 0.06), 0 8px 16px rgb(15 23 42 / 0.06), 0 16px 32px rgb(15 23 42 / 0.06);
Animating a shadow smoothly
.card { position: relative; box-shadow: 0 1px 3px rgb(0 0 0 / 0.1); }
.card::after {
content: ""; position: absolute; inset: 0; border-radius: inherit;
box-shadow: 0 20px 40px -12px rgb(0 0 0 / 0.25);
opacity: 0; transition: opacity 200ms ease-out;
pointer-events: none;
}
.card:hover::after { opacity: 1; }
Rounding the corners too? Use the border radius generator. Choosing the shadow color? The color converter turns any color into rgb(), hsl() or oklch().
Frequently asked questions
What do the four box-shadow lengths mean?
In order: horizontal offset (positive moves the shadow right), vertical offset (positive moves it down), blur radius (how soft the edge is; it can’t be negative) and spread (positive grows the shadow in every direction, negative shrinks it). Only the two offsets are required; blur and spread default to 0. Add inset to draw the shadow inside the box.
Why use several shadow layers?
Real shadows have a dark, sharp core close to the object and a lighter, wider falloff. Stacking a few layers with doubling offsets and blur, each at low opacity, imitates that and looks much more natural than one big blurry shadow. Try the “Layered (smooth)” preset. A small negative spread keeps a large shadow from peeking out at the sides.
box-shadow or filter: drop-shadow()?
box-shadow follows the element’s box and border-radius, supports spread, inset and several layers, and is what you want for cards and buttons. filter: drop-shadow() follows the visible pixels, including transparent PNGs, SVG shapes and clipped elements, but has no spread or inset.
Are box shadows bad for performance?
Drawing a static shadow is cheap. Animating box-shadow is not, because every frame repaints the shadow, which can stutter with large blurs. To animate a shadow on hover, put the larger shadow on a ::after pseudo-element and animate its opacity instead, which the browser can do on the GPU.
How do I use the shadow in Tailwind?
Copy the Tailwind line: it’s an arbitrary value like shadow-[0_4px_12px_rgb(0_0_0/0.15)], with spaces replaced by underscores. To reuse it, add it to your theme as a named shadow (--shadow-card in Tailwind 4, or theme.extend.boxShadow in Tailwind 3).