Box shadow generator for a full CSS elevation scale
Most CSS shadow generators give you one shadow. This one builds three to ten, grown from a few simple rules, so your cards, menus, and dialogs share one depth system. Tune blur, spread, opacity, and offset, test light and dark backgrounds, then copy code for CSS, Tailwind, React Native, text-shadow, or drop-shadow.
The scale is calculated in your browser as you move the sliders. Nothing you enter is uploaded. The output uses standard CSS, so it works in any framework.
You can finish a first pass in about three minutes.
1
Pick a preset
Start from Material Design, Soft UI, Sharp Depth, or Glow. Each preset sets every slider, so you begin with a working scale instead of a blank one.
2
Set the shadow color
Use black for neutral depth, or a darkened tint of your surface color for a softer look. The preview updates as soon as you enter a valid 6-digit hex value.
3
Shape the curves
Adjust blur, spread, opacity, and offset growth. Change one curve at a time and compare the first and last levels in the preview, because they show the full range.
4
Check light and dark backgrounds
Switch the preview background. If the low levels disappear on dark, plan a dark-mode override before you ship.
5
Copy the code
Choose CSS variables, Tailwind v4, Tailwind v3, React Native, text-shadow, or drop-shadow output, then paste the block into your project.
BOX-SHADOW SYNTAX
How a CSS box-shadow value works
Every box-shadow is a short list of values. Once you know what each one does, the sliders above stop feeling like guesswork.
Moves the shadow right (positive) or left (negative).
Keep it at 0 for light from directly above. Use small values for a side light source.
offset-y
Moves the shadow down (positive) or up (negative).
This carries most of the depth. A raised element usually needs a larger Y than X.
blur-radius
Softens the edge. It cannot be negative.
Higher blur reads as more distance from the surface. It is the main difference between levels.
spread-radius
Grows or shrinks the shadow before blur is applied.
Small negative values pull the shadow in under the element, which avoids a halo on the sides.
color
Sets the shadow color and its alpha.
Prefer rgba or a tinted color at 8 to 20% alpha over solid black.
inset
Draws the shadow inside the box.
Good for pressed buttons and text fields. Text-shadow and drop-shadow do not support it.
You can stack several shadows in one declaration by separating them with commas. The first shadow sits on top. Designers use this to combine a tight key shadow with a wide ambient one, which is what the layered option in the generator does.
WHICH PROPERTY
Box shadow, drop shadow, or text shadow?
The three properties look similar but follow different shapes. Pick by what the shadow should trace.
Property
Follows
Spread
Inset
Best for
box-shadow
The element box and its border-radius
Yes
Yes
Cards, buttons, inputs, menus, modals
filter: drop-shadow()
The visible pixels, including transparency
No
No
PNG and SVG icons, clipped or irregular shapes
text-shadow
The shapes of the letters
No
No
Text over images, headings with a soft glow
When drop-shadow wins
A transparent PNG logo or an SVG icon has no visible box, so box-shadow draws a rectangle around empty space. drop-shadow traces the actual shape. It also works on a parent whose child is clipped with clip-path, where box-shadow gets cut off.
When text-shadow helps
White headings on a photo often lose contrast. A soft, low-opacity text-shadow behind the letters lifts them without adding an overlay. Keep the blur small so the text stays sharp. The text-shadow tab above converts your scale into matching values.
ELEVATION SCALE
Why one scale beats one-off shadows
Elevation is the sense that some parts of an interface sit higher than others. A raised element casts a bigger, softer, lower shadow. In a real product, the trouble starts when each developer copies a different value. After a year you have a dozen unrelated shadows, and a tooltip can end up looking heavier than the dialog behind it.
A scale fixes this by turning shadows into a short ladder of tokens. The generator grows blur on a curve, so it opens faster at higher levels, and lets opacity, spread, and offset grow at their own rates. Four to six levels cover almost every interface.
Which level goes on which component
Component
Level (6-level scale)
Reason
Resting card, list item
L1–L2
A gentle lift. Pair it with a 1px border on white surfaces.
Hovered card
One above rest
The jump signals the element is interactive.
Sticky header
L2–L3
Needs to separate from scrolling content without dominating it.
Dropdown, select menu
L3–L4
Floats over content but stays below dialogs.
Tooltip, popover
L3–L4
Same tier as menus. A tooltip must never look higher than the dialog it sits inside.
Toast
L4–L5
Must stand out from the page but should not compete with a modal.
Drawer, side panel
L5
Large surface, so a wide soft shadow works better than a tight one.
Dialog, modal
Top level
Highest layer in the interface. Pair it with a dimmed backdrop.
Layered shadows in plain terms
Real light produces two effects: a sharp shadow right under the object and a wide, faint one around it. A single CSS shadow cannot do both. Two shadows stacked in one declaration can. Turn on Layered shadows and compare level 4 with the option off. The difference is usually easy to see on a white surface.
Opacity growth is a judgment call
Some systems keep the same opacity at every level, because more blur already spreads the shadow thin. Others raise opacity a little so high levels still register. Start with a small growth. If level 6 looks washed out, add more. If it looks heavy, set growth to zero.
Run the search command above to list every box-shadow value in your codebase. Most teams find 10 or more unique values.
Group them by the role of the component: resting, raised, floating, overlay.
Generate a scale here with the same number of groups, and pick the preset closest to your current look.
Replace each raw value with a token. Review one component family at a time so visual changes stay easy to spot.
Add a review rule: new shadows must use a token. This keeps the scale intact after launch.
COMMON MISTAKES
Six shadow mistakes and how to fix them
These come up again and again in code reviews.
A parent with overflow: hidden clips the shadow
The shadow is drawn outside the element box, so any ancestor that clips overflow cuts it off. This is the most common reason a shadow looks broken.
Add padding to the clipping parent equal to the blur plus offset, or move overflow: hidden to an inner wrapper.
Solid black at high opacity
A 40% black shadow looks dirty on white and heavy on tinted surfaces. It also makes every card feel the same weight.
Stay between 8% and 20% for most levels. Tint the color toward your surface hue for a cleaner result.
One shadow for every component
When a card, menu, and dialog share a shadow, users lose the sense of which layer is on top.
Assign levels by stacking order. Anything that opens above something else gets a higher level.
Animating box-shadow directly
Each animation frame repaints the element. On a list of 30 cards, hover effects can drop frames.
Put the target shadow on a pseudo-element and animate its opacity. The example in the performance section shows how.
Using a shadow as the only edge on inputs
A faint shadow rarely reaches the 3:1 contrast WCAG asks for on the boundary of an interface component.
Give inputs a real border. Use the shadow as extra depth, not as the outline.
Never checking dark mode
Dark shadows on a dark surface disappear, so the interface goes flat and layers merge.
Override the shadow variables under a dark selector. The dark mode section lists three approaches.
DARK MODE
Making shadows work in dark mode
A dark shadow needs a lighter surface to show against. On a dark background, the same values that look right on white almost vanish. Use the Dark preview button in the tool to see this for yourself, then pick one of these approaches.
Raise the opacity
Move from about 14% to 30 to 50%. It is the fastest fix and keeps your markup unchanged.
Lighten higher surfaces
Make each level a slightly lighter shade of the base surface. Depth then comes from color, and the shadow only adds definition.
Switch to a glow
Use a tinted, centered shadow for accent elements such as primary buttons. It reads well on dark surfaces.
Because the tool outputs CSS variables, the override is a few lines:
iOS reads shadowColor, shadowOffset, shadowOpacity, and shadowRadius. Android reads elevation. Set both, and test on a real Android device.
import { shadows } from "./shadows"
<View style={[styles.card, shadows.elevation2]} />
Converting CSS shadows to React Native
The CSS blur radius is roughly twice the iOS shadowRadius, so the generator halves it. Spread has no equivalent in these props, and only the primary layer is exported. Android ignores the iOS props and draws its own shadow from elevation, so the exported elevation numbers are a starting point. Recent React Native versions also accept a CSS-style boxShadow prop. Check the documentation for your version before relying on it.
PERFORMANCE
Keep shadows fast and stable
Shadows cannot cause layout shift
A box-shadow takes up no layout space, so changing or adding one never moves surrounding content. CLS problems near cards usually come from images or fonts, not shadows.
Animate opacity, not the shadow
Changing box-shadow forces a repaint on every frame. Fading a pseudo-element that already carries the final shadow is cheap and keeps interactions responsive.
Watch blur on long lists
Large blur radii cost more to paint. On virtualized lists with many cards, keep the blur modest and profile in your browser performance panel before shipping.
Respect reduced motion
Wrap shadow transitions in a prefers-reduced-motion check so people who turn off animation do not see them.
A hover elevation that animates opacity instead of box-shadow:
Every preset is a set of slider values. Change them freely after you pick one.
Material Design
Neutral, layered, and realistic.
Dashboards, admin tools, and any product where depth should feel natural and quiet.
Soft UI
Tinted, offset, and rounded.
Consumer apps and marketing pages with pastel or tinted surfaces.
Sharp Depth
Tight and high contrast.
Dense interfaces, data tables, and designs with crisp borders.
Glow
Centered and colored.
Dark themes, primary buttons, and status highlights.
FAQ
CSS shadow questions, answered
Direct answers on box-shadow, drop-shadow, Tailwind, React Native, and dark mode.
A CSS box shadow generator lets you adjust offset, blur, spread, and color with sliders and copy the resulting box-shadow value. This one goes further: it builds a whole scale of 3 to 10 related shadows, so every card, menu, and dialog in your interface shares one depth system.
box-shadow draws around an element's rectangular box and follows its border-radius. filter: drop-shadow() follows the visible shape, including transparent areas in a PNG or SVG. text-shadow follows the letter shapes. Only box-shadow supports spread and inset.
Most products need four to six. That covers resting cards, raised menus, popovers, drawers, and modals. Ten levels rarely produce differences people can see, and they make it harder for a team to choose the right one.
In Tailwind v4, paste the @theme block into your CSS file and use classes like shadow-elevation-3. In Tailwind v3, merge the boxShadow object into theme.extend in tailwind.config.js. The generator produces both formats.
Map the values to shadowColor, shadowOffset, shadowOpacity, and shadowRadius for iOS, and add an elevation number for Android. As a rule of thumb, shadowRadius is about half the CSS blur. Spread has no equivalent in these props. Newer React Native versions also accept a CSS-style boxShadow prop, so check your version.
A parent with overflow: hidden, auto, or scroll clips anything drawn outside its box, including shadows. Add padding to the parent so the shadow has room, or move the overflow rule to an inner wrapper.
Static shadows are cheap. Animating box-shadow forces a repaint on every frame, and large blur values make each repaint slower. For hover effects, put the target shadow on a pseudo-element and animate its opacity instead. Shadows take up no layout space, so they never cause layout shift.
Dark surfaces hide dark shadows. Raise shadow opacity, lighten the surface color of higher levels, or both. Define shadows as CSS variables so you can override the whole scale in a dark-mode selector.
No. The scale is calculated in your browser as you move the sliders, and nothing you enter is uploaded.
Build your shadow scale
Pick a preset, tune the curves, and copy the code. It takes a few minutes.