The CSS box-shadow property adds one or more shadow effects around an element's box. Shadows are essential for creating depth, elevation and visual separation in modern UI design — buttons, cards, modals, dropdowns and tooltips all rely on them. Unlike image-based shadows, CSS box shadows are crisp at any resolution, load instantly, and can be animated.
Use the generator above to build single or multi-layer shadows visually, then copy the CSS directly into your project.
box-shadow: offset-x offset-y blur spread color; box-shadow: inset offset-x offset-y blur spread color; /* Multiple layers (comma-separated) */ box-shadow: 0 2px 4px rgba(0,0,0,0.1), 0 8px 24px rgba(0,0,0,0.15);
offset-x — Horizontal shadow position. Positive moves right, negative moves left.
offset-y — Vertical shadow position. Positive moves down, negative moves up.
blur-radius — How soft the shadow edge is. 0 = sharp. Higher = more diffused.
spread-radius — Expands or contracts the shadow size. Positive = larger than the element. Negative = smaller.
color — The shadow color. Use rgba() to control opacity.
/* Subtle card lift */ box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.08); /* Elevated modal */ box-shadow: 0 8px 32px rgba(0,0,0,0.24), 0 2px 8px rgba(0,0,0,0.12); /* Soft bottom shadow only */ box-shadow: 0 4px 16px -4px rgba(0,0,0,0.2); /* Coloured glow */ box-shadow: 0 0 0 1px #7c6fff, 0 0 20px rgba(124,111,255,0.4); /* Pressed button (inset) */ box-shadow: inset 0 2px 4px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.2); /* No shadow (reset) */ box-shadow: none;
The inset keyword moves the shadow inside the element boundary — useful for pressed button states, inner glow effects, and UI elements that need to appear recessed into the surface.
/* Input field focus ring using inset */
.input:focus {
box-shadow:
inset 0 1px 3px rgba(0,0,0,0.15),
0 0 0 3px rgba(124,111,255,0.25);
}
/* Inner glow */
.glow-card {
box-shadow: inset 0 0 30px rgba(124,111,255,0.2);
}
Real-world objects cast complex shadows with multiple components — a sharp close shadow and a soft diffuse shadow further away. Layering two shadows closely mimics this and produces much more realistic depth than a single layer.
/* Layered realistic shadow (low elevation) */
.card {
box-shadow:
0 1px 2px rgba(0,0,0,0.07),
0 2px 4px rgba(0,0,0,0.07),
0 4px 8px rgba(0,0,0,0.07);
}
/* High elevation — modal/dialog */
.modal {
box-shadow:
0 2px 4px rgba(0,0,0,0.08),
0 8px 16px rgba(0,0,0,0.1),
0 24px 48px rgba(0,0,0,0.12);
}
box-shadow can be transitioned, but it is expensive because it triggers a repaint on every frame. For animated hover effects, a performance trick is to pre-render the shadow using opacity: 0 on a pseudo-element and fade that in instead of transitioning box-shadow directly.
/* Simple transition (OK for occasional use) */
.card {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: box-shadow 0.25s ease;
}
.card:hover {
box-shadow: 0 8px 32px rgba(0,0,0,0.2);
}
box-shadow has been universally supported since 2011 — completely safe to use without prefixes or fallbacks. It respects border-radius, but does NOT follow clip-path shapes (use filter: drop-shadow() for that).
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| box-shadow | 10+ | 4+ | 5.1+ | 12+ |
| inset shadows | 10+ | 4+ | 5.1+ | 12+ |
| multi-layer | 10+ | 4+ | 5.1+ | 12+ |
| box-shadow animation | 26+ | 16+ | 7+ | 12+ |
Stack two shadows with opposite directions — one dark below-right, one light above-left, both on a background that matches the element. Example: box-shadow: 8px 8px 16px #b8b9be, -8px -8px 16px #ffffff. The element should share the same background color as its parent for the soft, embedded look.
Default (outset) shadows project outward from the element's edge. Adding the inset keyword flips the shadow inward, making the element appear pressed in or recessed. Inset shadows are useful for input field focus rings, pressed button states and recessed UI panels.
Use a small Y offset, a large blur radius, and low opacity: box-shadow: 0 8px 24px rgba(0,0,0,0.08). The key is high blur with low opacity. Stack a second tighter shadow for added depth: box-shadow: 0 8px 24px rgba(0,0,0,0.08), 0 2px 6px rgba(0,0,0,0.06).
Yes, but it's expensive — animating box-shadow forces a repaint every frame. For smooth performance, animate the opacity of a pseudo-element with the shadow on it, or use transform: scale() to fake elevation changes. The Animating box-shadow section above has the optimized pattern.
Use box-shadow for rectangular UI elements (cards, buttons, panels) — it's faster and respects border-radius. Use filter: drop-shadow() for irregular shapes — it follows transparent areas in PNGs and clip-path edges, which box-shadow can't do. For most UI work, box-shadow is the right choice.
Comma-separate them in a single box-shadow declaration. Each shadow renders top-down — the first shadow listed appears on top. Layering 2-4 shadows produces realistic depth: a tight inner shadow for the edge plus a wider outer shadow for ambient elevation.
Need a shadow that follows the actual shape of an element rather than its bounding box? Use our CSS Filter Generator with drop-shadow() instead.