How CSS box-shadow Works (with Examples)
The CSS box-shadow property draws one or more shadow layers behind (or inside) any HTML element. It takes up to six values: an optional inset keyword, horizontal offset, vertical offset, blur radius, spread radius, and color. Because shadows render entirely in the browser without any image assets, they are zero-cost to change and work on any element from a button to a full page card.
The full syntax at a glance
The formal syntax for a single shadow layer looks like this:
box-shadow: [inset] offset-x offset-y [blur-radius] [spread-radius] color;
Every value in square brackets is optional — only the two offsets and the color are required. Multiple shadow layers are separated by commas:
/* Single shadow */
box-shadow: 4px 4px 12px rgba(0, 0, 0, 0.15);
/* Two layers stacked */
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.12),
0 4px 16px rgba(0, 0, 0, 0.08);
When the browser renders multiple layers, it draws them in order — the first item in the list appears on top, the last at the bottom.
What each parameter does
| Parameter | Required? | What it controls |
|---|---|---|
inset | No | Moves the shadow inside the element instead of behind it |
offset-x | Yes | Horizontal shift; positive moves right, negative moves left |
offset-y | Yes | Vertical shift; positive moves down, negative moves up |
blur-radius | No (default 0) | How soft the edges are; higher values mean more diffuse shadows |
spread-radius | No (default 0) | Expands or shrinks the shadow before blurring; can be negative |
color | Yes* | Any CSS color value; rgba() gives you opacity control |
*Technically optional in the spec — browsers fall back to currentColor — but omitting it produces inconsistent results across browsers. Always specify the color explicitly.
Blur vs. spread: the distinction that trips people up
These two parameters are the most commonly confused, because both make a shadow look "bigger." They do different things:
- Blur radius softens the edges of the shadow. A blur of
0gives you a hard, crisp shadow with clean pixel edges. A blur of20pxspreads that edge over 20 pixels, creating the soft glow effect you see in most modern card designs. The shadow's core area stays the same size as the element; only the feathered edge grows. - Spread radius resizes the shadow before the blur is applied. A spread of
8pxmakes the shadow 8 pixels larger on every side. A spread of-8pxshrinks it by 8 pixels on every side. This is especially useful when you want a focused shadow that sits close underneath an element rather than bleeding out in all directions.
The inset keyword
Adding inset as the very first token flips the shadow from behind the element to inside it. This is the standard way to create pressed-button effects, recessed panels, and inner glow.
/* Normal outward shadow */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
/* Inset shadow — shadow appears inside the element */
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.15);
Inset shadows obey the same offset rules: positive offset-x shifts the shadow right inside the element, positive offset-y shifts it down. A common pattern is a small inset shadow on the top of a button's resting state and a larger one when the button is :active, simulating physical depth.
Multi-layer shadows for realistic depth
Real-world light rarely produces a single uniform shadow. Most polished UI components stack two or three shadow layers to create a more convincing sense of elevation. The typical approach is:
- A tight, dark, low-offset shadow to ground the element to the surface directly below it.
- A wider, lighter, higher-offset shadow to represent the softer ambient light that wraps around the element at a distance.
/* Layered shadow for a floating card */
.card {
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.10), /* contact shadow */
0 8px 24px rgba(0, 0, 0, 0.08); /* ambient shadow */
}
Google's Material Design uses this technique systematically — each elevation level has a characteristic pair of shadows that together communicate how high the surface is above the page. You do not need to copy their exact values, but the two-layer pattern translates well to any design system.
rgba(30, 60, 120, 0.12) on a blue card — for a more cohesive result.
Common practical patterns
Soft card lift
.card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
}
Glowing focus ring (replaces outline)
button:focus-visible {
outline: none;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.5);
}
Here both offsets are 0, blur is 0, and spread is 3px — the result is a solid ring around the element, which is a clean way to build custom focus indicators. Using box-shadow instead of outline means the ring respects border-radius.
Neumorphic surface
.neu-button {
box-shadow:
6px 6px 12px rgba(0, 0, 0, 0.12),
-6px -6px 12px rgba(255, 255, 255, 0.9);
}
Neumorphism stacks a dark shadow on one side with a light (near-white) shadow on the opposite side, creating the illusion of a surface extruded from the background. It works best when the element background color matches the page background closely.
Performance and browser support
box-shadow is supported in every browser in use today — it has been part of CSS3 since before Internet Explorer 9. For animation performance, the browser has to repaint the shadow on every frame when you transition it, which can be expensive on mobile. The standard recommendation is to animate opacity or transform instead of box-shadow values directly, and use a pseudo-element or layered elements if you need smooth shadow transitions at high frame rates.
For most static or hover-triggered shadows, this is not a practical concern. Only optimize if you observe dropped frames in DevTools performance profiling.
Build your shadow visually
Figro's CSS box-shadow generator lets you drag sliders for every parameter — offset, blur, spread, opacity, color — and watch the shadow update in real time. Add multiple layers, choose from common presets, and copy the finished CSS, React, or Tailwind syntax instantly. Free, no signup, everything runs in your browser.
Open the free CSS box-shadow generator →Figro's guides are educational and independent. They are not design or engineering advice. Some pages include affiliate links; if you purchase through them we may earn a commission at no extra cost to you.