The syntax
box-shadow: [inset] offset-x offset-y blur-radius spread-radius color;Only offset-x, offset-y, and color are required — blur and spread default to 0 if omitted. A minimal usable shadow is just:
box-shadow: 2px 4px rgba(0, 0, 0, 0.25);Each value, explained
- offset-x — horizontal position. Positive pushes the shadow right, negative pushes it left.
- offset-y — vertical position. Positive pushes the shadow down, negative pushes it up. Most natural-looking shadows use a positive offset-y and little or no offset-x, mimicking an overhead light source.
- blur-radius — how soft the shadow's edge is.
0gives a hard-edged silhouette; larger values spread the shadow into a soft gradient. Never negative. - spread-radius — grows or shrinks the shadow's shape before blurring is applied. Positive values make the shadow larger than the element in every direction; negative values shrink it — useful for tightening a shadow that a large blur radius has spread too far.
- color — almost always a partially transparent black or a color matching the background, e.g.
rgba(0, 0, 0, 0.25). A fully opaque shadow color looks like a flat shape, not a shadow. - inset — the one keyword in the property. Placed first, it flips the shadow from an outer drop shadow to an inner one that appears to recede into the surface — used for pressed buttons, input fields, and inset panels.
Layering multiple shadows
box-shadow accepts a comma-separated list, and every real-world "elevation" system (Material Design's included) uses two or three stacked shadows rather than one. A single large blurred shadow looks flat and artificial; combining a tight, low-opacity shadow with a larger, softer one reads as more physically plausible:
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.12),
0 4px 12px rgba(0, 0, 0, 0.10);The first line simulates a close, sharp contact shadow; the second simulates ambient light falloff.
Common patterns
- Card elevation: small offset, moderate blur, low opacity —
0 2px 8px rgba(0,0,0,0.1). - Focus ring: zero blur, larger spread, brand color instead of black —
0 0 0 3px rgba(99,102,241,0.4)— a common accessible alternative tooutlinethat respects border-radius. - Pressed / inset button:
inset 0 2px 4px rgba(0,0,0,0.25). - Neumorphism (soft embossed UI): two shadows on opposite corners, one light and one dark, both low-contrast against the background —
-6px -6px 12px rgba(255,255,255,0.7), 6px 6px 12px rgba(0,0,0,0.15).
Performance note
Large blur radii are more expensive to paint than small ones, and animating box-shadow directly (e.g. on hover) forces the browser to repaint rather than composite on the GPU. For a shadow that changes on hover, animating opacity on a separate pseudo-element with a fixed shadow is noticeably smoother than animating the box-shadow value itself.