CSS Box Shadow Generator: Design & Copy Shadow CSS
Key Takeaways
- ▸Figma's Drop Shadow maps directly to
box-shadow— but color opacity must be manually converted torgba(), and Inner Shadow requires theinsetkeyword. - ▸Blur and spread are not the same: blur softens the shadow edge, spread expands the shadow shape before blurring. Conflating them is the most common
box-shadowmistake. - ▸
box-shadowhas 99%+ browser support per Can I Use — no vendor prefix needed since 2012. Multiple shadows and inset are fully supported everywhere. - ▸Use
filter: drop-shadow()for non-rectangular elements (PNGs with transparency, SVGs, clip-path shapes) —box-shadowalways follows the rectangular bounding box. - ▸Layering two or three shadows at different blur radii creates physically accurate depth — the technique used by Material Design 3 and Apple HIG. Single-shadow cards look flat in comparison.
You open a Figma handoff file for a new card component. The designer has applied a Drop Shadow with these values: X: 0, Y: 8, Blur: 24, Spread: -4, Color: #000000 at 20% opacity. You switch to the CSS panel in Figma and it gives you box-shadow: 0px 8px 24px -4px rgba(0, 0, 0, 0.2). Close enough — but then you notice the designer also added an Inner Shadow on the top edge to simulate ambient light: X: 0, Y: 2, Blur: 4, Spread: 0. Figma's CSS export gives you nothing for this. The panel just ignores it.
This is a real handoff gap that trips up even experienced developers. The inner shadow needs the inset keyword in CSS — a concept that does not appear anywhere in Figma's UI labels. And the stacking order is reversed: Figma renders the inner shadow over the drop shadow, but in CSS the first comma-separated shadow is on top. Get the order wrong and your card looks subtly different than the design.
This guide walks through every dimension of box-shadow: the full parameter anatomy, the blur-vs-spread confusion, inset mechanics, multi-shadow layering, performance trade-offs vs filter: drop-shadow(), and a complete shadow design system you can drop into any project. Use BytePane's CSS Formatter to clean up the output before committing.
CSS box-shadow Syntax: Full Anatomy
The formal box-shadow syntax defined in CSS Backgrounds and Borders Module Level 3:
box-shadow: [inset] <offset-x> <offset-y> [<blur-radius>] [<spread-radius>] <color>;
/* Minimal — just offsets and color */
box-shadow: 4px 4px black;
/* Full 5-value form */
box-shadow: 0px 8px 24px -4px rgba(0, 0, 0, 0.20);
/* │ │ │ │ └── color (rgba/hsla/hex)
│ │ │ └────── spread-radius (-4px shrinks the shadow)
│ │ └─────────── blur-radius (24px = soft diffused edge)
│ └──────────────── offset-y (8px downward)
└───────────────────── offset-x (0 = centered horizontally) */
/* Inset (inner shadow) */
box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.15);
/* Multiple shadows — first is rendered on top */
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.08), /* top highlight */
0 4px 8px rgba(0,0,0,0.12), /* close ambient */
0 16px 32px rgba(0,0,0,0.08); /* far diffused */Each Parameter Explained
offset-x — Horizontal displacement. Positive values move the shadow right, negative values move it left. Zero keeps the shadow centered. A large positive offset like 8px implies a light source to the upper-left.
offset-y — Vertical displacement. Positive pushes the shadow downward (most common — simulates overhead light). Negative values pull the shadow above the element (simulates a light source below, used for glowing floor effects).
blur-radius — Controls edge softness. At 0, the shadow has a sharp hard edge (like a physical cutout). As blur increases, the shadow spreads outward and fades. A value of 24px produces a soft, diffused shadow. Negative values are not allowed. This parameter cannot be negative.
spread-radius — Expands or contracts the shadow shape before blur is applied. 4px spread makes the shadow 4px larger on all sides. -4px shrinks the shadow, which is commonly paired with a large blur to produce a more realistic, concentrated shadow (it prevents the "glow" effect of a large blur with zero spread). This is the parameter most developers skip — but it is essential for photorealistic shadows.
color — The shadow color, including alpha. In practice, shadows should almost never be pure black (#000) — they should be a semi-transparent dark (e.g., rgba(0,0,0,0.2)) so the background color bleeds through, matching physical shadow behavior.
The Blur vs Spread Confusion — Cleared Up
According to the State of CSS 2024 survey by Lea Verou and the CSS Working Group team, box-shadow is among the top 10 CSS properties developers report as "confusing to use correctly." The blur/spread distinction is the core reason. Here is the mental model:
/* BLUR controls edge softness — the shadow total size changes, but softly */
box-shadow: 0 4px 0px 0 rgba(0,0,0,0.3); /* blur=0: sharp hard edge */
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.3); /* blur=8: slightly softened */
box-shadow: 0 4px 32px 0 rgba(0,0,0,0.3); /* blur=32: very diffused */
/* SPREAD controls shadow SIZE before blur runs */
box-shadow: 0 4px 16px -8px rgba(0,0,0,0.3); /* spread=-8: shrunken, concentrated */
box-shadow: 0 4px 16px 0px rgba(0,0,0,0.3); /* spread=0: normal */
box-shadow: 0 4px 16px 8px rgba(0,0,0,0.3); /* spread=8: larger shadow footprint */
/* The "shrink-to-concentrate" technique used in premium UI */
/* Large blur + negative spread = realistic shadow that doesn't bleed */
box-shadow: 0 20px 60px -12px rgba(0, 0, 0, 0.35);The practical takeaway: if your shadow looks like a glowing aura instead of a grounded drop shadow, add a negative spread. A value of roughly -(blur / 3) is a common rule of thumb to tighten the shadow back toward the element.
Inset Shadows: Inner Shadows from Figma to CSS
Figma calls it "Inner Shadow." CSS calls it inset. The mapping is direct — add the inset keyword before the offset values. The shadow renders inside the element's border box instead of outside.
Inset shadows are useful for: pressed/active button states (the "pushed in" effect), input fields that look recessed, cards with an inner top-edge highlight simulating ambient light, and neumorphism UI (which is built entirely from paired inset and outset shadows).
/* Basic inset shadow — simulates a recessed surface */
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.2);
/* Pressed button state */
.btn:active {
box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.25);
transform: translateY(1px); /* subtle physical press feel */
}
/* Top-edge highlight (ambient light from above) */
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
/* Neumorphism: both inset light and shadow directions */
.neumorphic {
background: #e0e0e0;
box-shadow:
inset 6px 6px 12px #bebebe, /* inner shadow bottom-right */
inset -6px -6px 12px #ffffff; /* inner highlight top-left */
}
/* Combining inset with outer shadow (Figma equivalent) */
.card {
/* Figma: Drop Shadow + Inner Shadow stacked */
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.08), /* inner top highlight */
0 8px 24px -4px rgba(0, 0, 0, 0.20); /* outer drop shadow */
}
/* Common mistake: forgetting spread on inset makes it look weak */
/* Without spread, inset is just a thin tinted edge */
box-shadow: inset 0 0 12px rgba(0,0,0,0.2); /* weak — no directionality */
box-shadow: inset 0 4px 12px -2px rgba(0,0,0,0.3); /* better — directed + spread */One important note: inset on an element with overflow: hidden will be clipped correctly. On an element without overflow: hidden, the inset shadow still stays inside the border box — it is always masked to the element boundaries by definition. This is different from outer box-shadow, which gets clipped by parent overflow.
Multiple Shadows: Layering for Realism
Single-shadow cards look flat. Real physical objects cast multiple light interactions simultaneously — a tight ambient shadow close to the surface, and a diffused shadow that reaches farther. CSS comma-separated shadows let you replicate this behavior. The first shadow in the list renders on top (closest to the viewer), subsequent ones below:
/* One shadow — flat, unconvincing */
.card-flat {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
/* Two-layer shadow — more realistic depth */
.card-medium {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.12), /* close ambient */
0 8px 24px rgba(0, 0, 0, 0.08); /* far diffused */
}
/* Three-layer shadow — premium depth (Material Design technique) */
.card-deep {
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.10), /* surface level */
0 4px 8px rgba(0, 0, 0, 0.08), /* mid-distance */
0 16px 40px rgba(0, 0, 0, 0.06); /* atmospheric depth */
}
/* Colored shadow for brand-tinted cards */
.card-purple {
box-shadow:
0 4px 8px rgba(99, 102, 241, 0.15),
0 16px 40px rgba(99, 102, 241, 0.08);
}
/* Shadow stacking order example — first is on top */
.stacked {
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.1), /* rendered OVER the outer shadows */
0 4px 16px rgba(0,0,0,0.2), /* middle layer */
0 32px 64px rgba(0,0,0,0.1); /* bottom layer — farthest from viewer */
}Figma to CSS Translation: Exact Property Mapping
Figma's design panel exposes shadow values that map almost directly to CSS — but with three translation gotchas that cause subtle mismatches. The table below gives the complete mapping:
| Figma Property | CSS box-shadow Param | Translation Note |
|---|---|---|
| X | offset-x | Direct 1:1 mapping. Figma X=4 → CSS 4px |
| Y | offset-y | Direct 1:1 mapping. Figma Y=8 → CSS 8px |
| Blur | blur-radius | Direct 1:1 mapping. Figma Blur=24 → CSS 24px |
| Spread | spread-radius | Direct 1:1. Figma default is 0 — many devs omit this and it matches. |
| Color + Opacity % | color (rgba alpha) | Gotcha: Figma's opacity slider is 0–100. CSS alpha is 0–1. Figma 20% → CSS rgba(0,0,0,0.2) |
| Inner Shadow type | inset keyword | Gotcha: Figma does not export inset keyword. Must be added manually. |
| Multiple shadows (layer order) | comma-separated order | Gotcha: In Figma, top layer renders last in the layer panel. In CSS, first comma = rendered on top. |
The color translation is the most error-prone step. A Figma shadow with color #1A1A2E at 30% opacity becomes rgba(26, 26, 46, 0.3) in CSS. Figma's Dev Mode now shows this automatically for most properties, but Inner Shadow is still exported as a comment at best. Always verify in browser DevTools against the Figma comp.
Shadow Comparison: Flat, Subtle, Dramatic
The following table covers three shadow tiers with CSS values, intended use cases, and visual descriptions. These match the elevation system approach used by Google Material 3 and Apple HIG:
| Tier | CSS Value | Visual Description | Use Case |
|---|---|---|---|
| Flat / None | box-shadow: none | No depth, flush with surface | Inline elements, disabled states, resting input fields |
| Hair | 0 1px 2px rgba(0,0,0,0.08) | Barely perceptible lift | Chips, badges, list items, avatar rings |
| Subtle (sm) | 0 2px 4px rgba(0,0,0,0.06), 0 4px 8px rgba(0,0,0,0.04) | Light card lift, soft ambient | Form cards, resting buttons, nav bars |
| Standard (md) | 0 4px 8px rgba(0,0,0,0.10), 0 8px 24px rgba(0,0,0,0.06) | Clear elevation, natural depth | Product cards, sidebars, interactive cards |
| Raised (lg) | 0 8px 16px rgba(0,0,0,0.12), 0 16px 48px rgba(0,0,0,0.08) | Prominent floating element | Hover states, featured pricing card, FAB |
| Elevated (xl) | 0 16px 32px -4px rgba(0,0,0,0.18), 0 32px 64px rgba(0,0,0,0.10) | High-floating, dramatic depth | Modals, dialogs, dropdowns, tooltips |
| Dramatic (2xl) | 0 24px 48px -8px rgba(0,0,0,0.25), 0 48px 96px rgba(0,0,0,0.12) | Cinematic depth, popping off page | Hero product images, full-screen overlays |
Shadow Color: rgba vs hsla vs Hex Alpha
Shadow color with transparency can be specified in three ways in modern CSS. Browser support differences matter for your baseline:
/* rgba() — 99%+ support, the standard choice */
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.20);
/* hsla() — 99%+ support, useful when color matches a theme hue */
box-shadow: 0 8px 24px hsla(240, 100%, 5%, 0.20); /* deep blue-black shadow */
/* 8-digit hex (#RRGGBBAA) — 94%+ support (no IE11, no legacy Edge) */
box-shadow: 0 8px 24px #00000033; /* #000000 = black, 33 = 20% opacity in hex */
/* oklch with alpha — 93%+ support (CSS Color Level 4) */
box-shadow: 0 8px 24px oklch(0% 0 0 / 0.20); /* perceptually black with 20% alpha */
/* CSS custom property for theme-aware shadows */
:root {
--shadow-color: 0deg 0% 0%; /* HSL components without hsl() wrapper */
}
.card {
box-shadow:
0 2px 4px hsl(var(--shadow-color) / 0.10),
0 8px 24px hsl(var(--shadow-color) / 0.08);
}
/* Dark mode: shift shadow color to the theme hue */
[data-theme="dark"] {
--shadow-color: 220deg 40% 2%; /* slightly blue-tinted black for dark UI */
}The hsl(var(--shadow-color) / alpha) pattern — described by Josh W. Comeau in his CSS shadow design article — is particularly powerful for design systems. It lets you swap the entire shadow color palette by changing one CSS variable, adapting shadows from dark-tinted (for dark mode) to warm-tinted (for earthy themes) automatically. You can use BytePane's color format guide to convert between shadow color formats.
Performance: box-shadow vs filter: drop-shadow()
Both properties produce visually similar results on rectangular elements — but they run in fundamentally different rendering stages in the browser's compositing pipeline. According to Chromium rendering documentation, box-shadow is computed during the paint phase on the CPU layer, while filter: drop-shadow() runs on a composited GPU layer.
| Property | Rendering Phase | Alpha Awareness | Best For |
|---|---|---|---|
| box-shadow | CPU paint layer | No — always rectangular bounding box | Rectangular elements (divs, buttons, cards) |
| filter: drop-shadow() | GPU composited layer | Yes — traces actual alpha channel | PNGs with transparency, SVGs, clip-path shapes |
/* box-shadow: always rectangular — ignores transparent PNG cutout */
.icon-png {
box-shadow: 0 8px 24px rgba(0,0,0,0.2); /* shadows the box, not the icon shape */
}
/* filter: drop-shadow — traces the actual icon alpha channel */
.icon-png {
filter: drop-shadow(0 8px 24px rgba(0,0,0,0.2)); /* shadows the icon contour */
}
/* filter: drop-shadow syntax (note: no spread-radius parameter) */
filter: drop-shadow(offset-x offset-y blur-radius color);
/* ⚠️ No spread parameter — drop-shadow only takes 3 values + color */
/* Performance trade-off: animated shadows */
/* ❌ Slow: animating box-shadow triggers paint on every frame */
.card:hover { box-shadow: 0 16px 40px rgba(0,0,0,0.3); } /* triggers repaint */
/* ✅ Fast: animate opacity on a pseudo-element instead */
.card::after {
content: '';
position: absolute; inset: 0;
box-shadow: 0 16px 40px rgba(0,0,0,0.3);
opacity: 0;
transition: opacity 0.2s ease; /* opacity is GPU-composited */
}
.card:hover::after { opacity: 1; }
/* Or use filter: drop-shadow on an absolutely positioned wrapper */
.card-wrapper {
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));
transition: filter 0.2s ease; /* filter transition is GPU-accelerated */
}
.card-wrapper:hover {
filter: drop-shadow(0 16px 32px rgba(0,0,0,0.2));
}For unanimated shadows on standard rectangular UI elements — cards, buttons, modals — box-shadow is the correct choice. Reserve filter: drop-shadow() for irregular shapes. For animated shadows at 60fps, the pseudo-element opacity trick is the fastest technique regardless of which shadow property you use.
Real-World Shadow Design Systems
Google Material 3 Elevation
Material Design 3 uses a five-level elevation system (0–5 dp) backed by box-shadow values. Rather than raw shadow CSS, Material 3 uses an elevation tonal overlay on dark surfaces (a color tint applied at opacity to indicate height) combined with shadows on light surfaces. The actual box-shadow values from the Material 3 specification:
/* Material Design 3 — shadow elevation scale */
/* Elevation 0dp — flush */
box-shadow: none;
/* Elevation 1dp — cards, navigation drawer */
box-shadow:
0px 1px 2px rgba(0,0,0,0.30),
0px 1px 3px 1px rgba(0,0,0,0.15);
/* Elevation 2dp — floating action button resting */
box-shadow:
0px 1px 2px rgba(0,0,0,0.30),
0px 2px 6px 2px rgba(0,0,0,0.15);
/* Elevation 3dp — FAB pressed, bottom navigation */
box-shadow:
0px 1px 3px rgba(0,0,0,0.30),
0px 4px 8px 3px rgba(0,0,0,0.15);
/* Elevation 4dp — navigation bar, snackbar */
box-shadow:
0px 2px 3px rgba(0,0,0,0.30),
0px 6px 10px 4px rgba(0,0,0,0.15);
/* Elevation 5dp — dialogs, modals */
box-shadow:
0px 4px 4px rgba(0,0,0,0.30),
0px 8px 12px 6px rgba(0,0,0,0.15);Apple HIG Shadow Values
Apple's Human Interface Guidelines uses more diffused, warmer shadows with lower opacity than Material Design. macOS and iOS shadow behavior (approximated in CSS):
/* Apple-style shadows — warmer, more diffused */
/* macOS window drop shadow approximation */
.macos-window {
box-shadow:
0 2px 4px rgba(0,0,0,0.06),
0 4px 8px rgba(0,0,0,0.06),
0 8px 16px rgba(0,0,0,0.06),
0 16px 32px rgba(0,0,0,0.06),
0 32px 64px rgba(0,0,0,0.06);
/* Apple stacks many low-opacity layers for a "soft light" effect */
}
/* iOS card sheet shadow */
.ios-sheet {
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08); /* upward — sheet rises from bottom */
}
/* iOS button pressed state */
.ios-btn:active {
box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);
filter: brightness(0.95);
}Tailwind CSS Shadow Scale
Tailwind CSS ships a named shadow scale from shadow-sm to shadow-2xl. These are the exact values from Tailwind's source (also valid standalone CSS variables):
/* Tailwind CSS v3/v4 shadow scale — exact values */
.shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }
.shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
.shadow-md { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); }
.shadow-lg { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); }
.shadow-xl { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }
.shadow-2xl { box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); }
.shadow-inner { box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); }
.shadow-none { box-shadow: 0 0 #0000; }Notice that Tailwind uses rgb(0 0 0 / 0.1) modern syntax (space-separated with slash alpha) rather than rgba(0,0,0,0.1). Both are equivalent in all browsers that support Tailwind, but the modern syntax is slightly cleaner. Tailwind v4 also allows customizing the shadow color via the --tw-shadow-color CSS variable.
CSS Variables for Theme-Aware Shadows
Hard-coding shadow opacity values is fine for single-theme sites, but dark mode UIs require rethinking shadows entirely. Dark backgrounds make dark shadows invisible — you need either lighter shadows, colored shadows, or a completely different elevation strategy. CSS custom properties make this manageable:
/* Design token approach for multi-theme shadows */
:root {
/* Shadow color tokens (H S L components, used with hsl()) */
--shadow-color-h: 220;
--shadow-color-s: 40%;
--shadow-color-l: 2%;
/* Named shadow tokens */
--shadow-sm: 0 1px 2px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.10);
--shadow-md: 0 4px 8px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.12),
0 1px 3px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.08);
--shadow-lg: 0 8px 24px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.14),
0 2px 6px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.08);
--shadow-xl: 0 20px 48px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.20),
0 8px 16px hsl(var(--shadow-color-h) var(--shadow-color-s) var(--shadow-color-l) / 0.10);
}
/* Light theme — warm brownish shadows */
[data-theme="light"] {
--shadow-color-h: 30;
--shadow-color-s: 30%;
--shadow-color-l: 8%;
}
/* Dark theme — shadows become color tints instead */
[data-theme="dark"] {
--shadow-color-h: 220;
--shadow-color-s: 60%;
--shadow-color-l: 2%;
}
/* Usage — automatically adapts across themes */
.card { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-xl); }
.btn:hover { box-shadow: var(--shadow-lg); }
/* Tailwind config: extend with your shadow tokens */
/* tailwind.config.js */
module.exports = {
theme: {
extend: {
boxShadow: {
'brand-sm': '0 2px 8px rgba(99, 102, 241, 0.15)',
'brand-md': '0 4px 16px rgba(99, 102, 241, 0.20), 0 2px 6px rgba(99, 102, 241, 0.10)',
'brand-lg': '0 8px 32px rgba(99, 102, 241, 0.25), 0 4px 12px rgba(99, 102, 241, 0.15)',
},
},
},
}Common box-shadow Mistakes
1. Using box-shadow on non-rectangular elements
Applying box-shadow to a PNG with a transparent background shadows the rectangle, not the subject. The fix is filter: drop-shadow(). The same applies to elements using clip-path — box-shadow renders on the original bounding box, not the clipped shape.
2. Forgetting spread on inset shadows
An inset shadow with zero spread and zero offset (inset 0 0 8px rgba(0,0,0,0.2)) just adds a soft vignette around the inside edges. To get a directional inset highlight — like ambient light from above — you need both an offset and optionally a spread to control how far the light reaches: inset 0 4px 12px -4px rgba(255,255,255,0.15).
3. Animating box-shadow directly
Transitioning box-shadow on hover works but triggers a repaint on each frame. For smooth 60fps hover shadow animations, use the pseudo-element opacity trick (set a ::after with the target shadow and opacity 0, transition opacity to 1 on hover) or wrap in a container and transition filter: drop-shadow().
4. Using opacity: on the element for shadow darkness
Setting opacity: 0.5 on the element to make the shadow look lighter also fades the content. Always control shadow darkness through the alpha channel in the shadow color value — rgba(0,0,0,0.1) — never through element opacity.
5. Pure black shadows
box-shadow: 0 8px 24px black looks harsh and artificial. Real-world shadows are semi-transparent so the surface color bleeds through. Use rgba(0,0,0,0.15) as a starting point, then adjust based on your background brightness. On dark backgrounds, consider a slightly colored shadow (matching the UI accent hue) to add visual interest.
Browser Support
According to Can I Use data as of 2026, box-shadow has 99.6%+ global browser support. The vendor-prefixed -webkit-box-shadow and -moz-box-shadow are not needed and have not been needed since 2012. MDN's browser compatibility table shows full support across Chrome (10+), Firefox (4+), Safari (5.1+), and Edge (12+). Multiple shadows, inset shadows, and spread radius are all covered in the same compatibility baseline.
filter: drop-shadow() has 98%+ support. The only gap is IE11 and very old mobile browsers. The State of CSS 2024 survey by Lea Verou showed box-shadow in the top 5 most-used CSS properties by usage frequency across surveyed developers — a testament to how universally deployed it is.
/* In 2026: no prefix needed */
box-shadow: 0 4px 16px rgba(0,0,0,0.15); /* ✅ correct */
/* Outdated — don't do this */
-webkit-box-shadow: 0 4px 16px rgba(0,0,0,0.15); /* ❌ unnecessary */
-moz-box-shadow: 0 4px 16px rgba(0,0,0,0.15); /* ❌ unnecessary */
box-shadow: 0 4px 16px rgba(0,0,0,0.15);Generate and Copy CSS Shadows Instantly
Use BytePane's CSS tools to build shadows visually, format your stylesheet, and generate gradient backgrounds for your cards. No login, no install — copy and ship.
Frequently Asked Questions
What is the CSS box-shadow syntax?
The full syntax is: box-shadow: offset-x offset-y blur-radius spread-radius color. Only offset-x, offset-y, and color are required. Multiple shadows are comma-separated. Add the inset keyword before the offsets to create an inner shadow. No vendor prefixes needed — box-shadow has 99%+ browser support since 2012.
What is the difference between blur and spread in box-shadow?
Blur controls the softness of the shadow edge — higher values produce a more diffused, feathered edge. Spread controls the size of the shadow shape before blurring — positive spread expands the shadow beyond the element bounds, negative spread shrinks it. Most developers confuse these: blur softens the edge, spread changes the overall shadow size.
How do I translate a Figma shadow to CSS box-shadow?
Figma Drop Shadow maps as: X → offset-x, Y → offset-y, Blur → blur-radius, Spread → spread-radius. The common gotcha: Figma's color opacity is 0–100, CSS alpha is 0–1. Figma 20% = CSS 0.2. Figma Inner Shadow needs the CSS inset keyword — Figma's dev panel does not export this automatically.
How do I add multiple shadows in CSS?
Comma-separate the shadow definitions: box-shadow: 0 2px 4px rgba(0,0,0,0.1), 0 8px 24px rgba(0,0,0,0.15). The first shadow in the list renders on top. Layering two or three shadows with different blur radii creates more realistic depth — the technique used by Material Design 3 and Apple HIG.
When should I use filter: drop-shadow instead of box-shadow?
Use filter: drop-shadow() for non-rectangular elements — PNG images with transparent backgrounds, SVG icons, and clip-path shapes. box-shadow always follows the element's rectangular bounding box, ignoring transparency. filter: drop-shadow() traces the actual alpha channel. Note: drop-shadow has no spread-radius parameter.
Does box-shadow affect layout or element size?
No. box-shadow is purely visual — it does not contribute to element size, does not push siblings, and does not affect the document flow. However, box-shadow is clipped by overflow: hidden on a parent. If you need a shadow that escapes overflow clipping, use filter: drop-shadow() on a parent wrapper instead.
Related Articles
CSS Gradient Generator Guide
Linear, radial, conic, and mesh gradients with copy-paste code.
Color Formats Explained
HEX, RGB, HSL, and OKLCH: when to use each color format.
CSS Flexbox Cheat Sheet
Every Flexbox container and item property with visual examples.
CSS Flexbox vs Grid
When to use each layout system with side-by-side comparisons.