CSS Box Shadow Generator
What it does
The Box Shadow Generator turns the five-parameter box-shadow CSS function into something you can tune by sight. Sliders control x/y offset, blur radius, and spread; a colour picker with an opacity slider sets the shadow tint; an inset toggle flips the shadow inward. The preview shows a real card-shaped element so the result looks like it would in production, not like an isolated swatch. The output is a single line of CSS you can paste straight into a stylesheet or design token file.
Common situations
You’re tuning the elevation system for a new product. The Material-style “Z=4dp = 4px shadow” approach feels dated; you want something more refined that still communicates depth. Iterating on a real card preview takes minutes; iterating in code takes hours.
You’re building a focus state for a custom-styled input that needs to look intentional rather than default-browser. An inset shadow plus an outer ring produces the “this field is active” feel that bare borders cannot match.
You’re producing print-ready marketing creative that needs the same elevation language as the digital product. A shadow that looks correct on screen often looks heavy in print — checking against a realistic preview catches the discrepancy before it becomes a vendor proof.
You’re debugging a shadow that “looks wrong on Windows but fine on Mac”. Both render the same CSS, but ClearType anti-aliasing, monitor calibration, and OS-level dark mode produce different perceived colours. Tuning to look right on both means starting at slightly higher contrast than feels right on the design Mac.
You’re moving from a shadow-heavy 2018 design to the cleaner 2026 standards — flatter elevation, lighter colours, more reliance on borders and subtle gradients than dramatic shadows. The generator is where you find the smaller, more deliberate values that current visual language calls for.
What you need to know
A box-shadow is five values plus a colour: x-offset, y-offset, blur radius, spread radius, colour. Optional inset makes the shadow appear inside the box rather than outside. The blur is what gives a shadow its softness — a 0px blur is a hard duplicate of the box, a 24px blur is the recognisable “elevation” effect. Spread expands or contracts the shadow before blurring, which is rarely useful for normal UI but indispensable for halo and glow effects.
Multiple shadows are valid — box-shadow accepts a comma-separated list, layered from first (top) to last (bottom). This is the technique used by Material Design’s elevation system: each “level” stacks two shadows (a sharp near-shadow plus a soft far-shadow) to produce more realistic depth than any single shadow can. box-shadow: 0 1px 2px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.05); is a typical card-elevation recipe.
The non-obvious part is the colour. Designers often default to pure black at low opacity, which produces a slightly grey, slightly cold shadow against most page backgrounds. Using a very dark version of the page’s primary brand colour at the same opacity produces a shadow that feels intentional rather than default — this is one of the small touches that separates polished design systems from “we used Tailwind defaults”.
There is a related but distinct property: filter: drop-shadow(). It applies to the visible shape of the element rather than its bounding box, which means a shadow on a non-rectangular element (clip-path, border-radius, transparent PNG) traces the actual shape. box-shadow traces the rectangle. Pick drop-shadow for irregular shapes and box-shadow for rectangles; the latter is more performant for animation.
For dark mode, increase blur and reduce opacity rather than lightening the shadow colour. Black-on-dark with a soft glow reads correctly; grey-on-dark looks like a print artefact.
Frequently asked questions
How do I make a CSS shadow?
Use the box-shadow property with five values: box-shadow: 0 4px 8px 0 rgba(0,0,0,0.1). Those are x-offset, y-offset, blur, spread, and colour. The first four control the shadow’s position and softness; the fifth controls its tint and opacity.
What’s the difference between box-shadow and drop-shadow?
box-shadow traces the element’s rectangular bounding box. filter: drop-shadow() traces the element’s actual rendered shape, including transparent regions and non-rectangular clipping. Use drop-shadow on icons, custom shapes, or images with transparent backgrounds; use box-shadow on rectangular cards.
Can I have multiple shadows on one element?
Yes — comma-separate them. box-shadow: 0 1px 2px black, 0 4px 8px gray applies both. The first listed shadow renders on top of the second. Most modern elevation systems use two-shadow stacks for realistic depth.
Why do my shadows look heavier on Windows than Mac?
Different anti-aliasing, different sub-pixel rendering, sometimes different default monitor profiles. Designs tuned exclusively on a Retina Mac often look heavier on standard Windows displays. Test on both; aim for the lighter end of acceptable on Mac so it does not over-render on Windows.
Are box shadows bad for performance?
Static shadows are essentially free — the browser renders them once. Animating shadows (changing them every frame) is expensive because each frame triggers a paint. For animated effects, prefer transform and opacity, which run on the GPU.
How do I create an “inner shadow” effect in CSS?
Use the inset keyword in the box-shadow value: box-shadow: inset 0 2px 4px rgba(0,0,0,0.2). Common for pressed-button states, focus rings on inputs, and recessed visual elements.
What shadow values does Material Design use?
Material’s elevation system defines 24 levels, each with a specific multi-shadow recipe. Level 4 (a typical card) uses approximately 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.20). The recipes are public on Material’s design site if you need to mirror that system specifically.
Should I use shadows in flat-design interfaces?
Even “flat” design uses subtle shadows for hierarchy — interactive elements, modals, focused states. Pure no-shadow interfaces struggle to communicate depth. The 2026 trend is minimal shadows (5–10% opacity, small blur) rather than no shadows at all.
Common problems
Problem: The shadow looks correct in design tools but wrong when shipped.
Design tools like Figma render shadows in their own colour space, which often differs slightly from browser rendering. The fix is to test the shipped page in the target browser and adjust the CSS values to match the design tool’s intent rather than its exact numerical output. Match the visual outcome, not the value.
Problem: Multiple stacked shadows produce a visible “edge” between them.
Each shadow in a stack is rendered separately and composited. If two shadows have very different blurs but similar offsets, the boundary between them becomes visible. Smooth the transition by using shadows with progressively scaling blur and offset values, not abrupt jumps.
Problem: Shadow on a parent element gets clipped by overflow:hidden.
overflow: hidden on an ancestor clips the shadow if the shadow extends beyond the ancestor’s bounds. Either move the shadow to a wrapper element that does not have overflow:hidden, or use filter: drop-shadow on the ancestor itself.
Problem: The shadow on a transparent PNG looks like a black box.
box-shadow traces the bounding rectangle, not the visible shape. For images with transparency where the shadow needs to follow the actual shape, switch to filter: drop-shadow(), which respects alpha channels.
Problem: Shadow disappears when applying transform: scale.
This is a known rendering quirk in some browsers — scaling can cause the shadow to be re-rasterised at the wrong resolution and appear missing. Adding will-change: transform on the scaling element typically resolves it; performance impact is minimal for short-lived animations.
Quick guides
Tailwind CSS: The default scale runs shadow-sm through shadow-2xl. Customise by extending theme.boxShadow in your config, or use arbitrary values like shadow-[0_4px_12px_rgba(0,0,0,0.08)] for one-off cases.
Design tokens: Define shadows as named tokens (shadow-card, shadow-modal, shadow-button-hover) rather than raw CSS values. Components reference the token; visual updates touch one place.
iOS / Android equivalents: iOS uses CALayer.shadow* properties (offset, radius, opacity); Android uses elevation plus the system shadow renderer. Neither maps perfectly to CSS — translating designs across platforms requires manual reinterpretation rather than direct value mapping.
Tips
- Pure top-down lighting reads as natural — y-offset only, no x. Setting x-offset to zero is almost always correct for general UI.
- Subtle wins. 5–15% alpha for elevation shadows. Anything above 25% starts feeling heavy and dated.
- Match the shadow’s blur radius to the element’s perceived elevation. A button hovering 4px off the page wants a 4–6px blur. A modal hovering 32px off the page wants 24–48px.
- For dark-mode designs, increase blur and reduce opacity rather than lightening the shadow colour.
- The inset variant builds “pressed” button states, focus rings on inputs, and inner-glow effects on dark UI.
- Stack two shadows (sharp near + soft far) rather than reaching for one large shadow. The two-shadow stack reads more realistically across most surfaces.
- Use a brand-coloured shadow (very dark version of your primary) instead of black for shadows on coloured backgrounds. The result feels designed rather than defaulted.
Related tools in this suite
The natural pairing is the Gradient Generator — gradients and shadows are the two CSS effects that distinguish polished interfaces from defaults, and they tend to be tuned alongside each other. The Border Radius Generator covers the third leg of that visual triumvirate; together they shape almost every UI surface beyond raw layout.
What this looks like at scale
A shadow value lives correctly in a design system, not in a stylesheet. Once you have a shadow you like, the next step is naming it (shadow-card, shadow-modal, shadow-button-hover) and using the name everywhere instead of repeating the value. The systems we build take that further — turning ad-hoc visual values into documented tokens that a content editor cannot accidentally drift away from.
Take it further
If shadow inconsistency across an interface is the symptom of a bigger systematisation problem, the work we do on design systems addresses the root: documented elevation scales, named tokens, and code-level enforcement that keeps shadows from drifting six months in.