A CSS box shadow generator is a visual editor that translates slider positions for offset, blur, spread, color, opacity, and inset into a single standards-shaped box-shadow declaration you can paste into any stylesheet. The CSS Box Shadow Generator produces one bounded shadow layer at a time, serializes it in the deterministic order defined by the CSS Backgrounds and Borders specification, and renders the effect on a local sample card so you can read the exact string before copying it. Every numeric input is validated against fixed ranges — offsets within ±200 px, blur within 0–200 px, spread within ±100 px, opacity within 0–100% — and the color is parsed as a six-digit hexadecimal value before its channels are converted to decimal rgba components. Because the preview and the serialized declaration update entirely in the browser, no shadow values, color choices, or clipboard contents leave the page. This makes the tool suitable for designing the one layer you actually want, not for guessing with arithmetic in your head.

What a Box Shadow Generator Actually Produces
Drop shadows are one of the most fiddly pieces of CSS to dial in by hand because every value interacts with the others. A 4-pixel offset looks crisp with zero blur but bleeds into a smear if the blur radius doubles the offset. A negative spread tightens the shadow around the box but eventually becomes invisible. Mixing rgba colors with three-digit shorthand, recomputing alpha from a percent, and remembering whether inset comes before or after the offsets adds small frictions that compound every time you iterate.
The CSS Box Shadow Generator is built around the same box-shadow component model described in CSS Backgrounds and Borders Level 3, so every knob on the page corresponds to a real property in the spec. You move sliders, the preview card updates instantly, and a plain-text declaration below the card reflects exactly what the browser will paint. The output is intentionally minimal: a single property, a single value, no selector, no style block, no vendor prefix, and no JavaScript. You copy it, paste it into a real rule for a real component, and inspect the result where it actually matters.
Inside the box-shadow Declaration, Token by Token
A box-shadow value has up to six pieces, and they always appear in a strict order when the generator serializes them. Optional inset comes first, followed by the horizontal offset, the vertical offset, the blur radius, the spread radius, and finally a color in rgba() notation. Drop any of the pixel lengths and the value stops being a valid box-shadow; change their order and the value still parses, but the result no longer matches what you saw in the preview.
The table below maps each control on the generator to its spec token, the range enforced by the tool, and what moving it actually does on screen.
| Control | CSS token | Tool range | Visible effect |
|---|---|---|---|
| Horizontal offset | First length | -200 to 200 px | Positive moves the shadow right; negative moves it left. |
| Vertical offset | Second length | -200 to 200 px | Positive moves the shadow down; negative moves it up. |
| Blur radius | Third length | 0 to 200 px | Zero is a hard edge; larger values soften and expand the visible transition without changing the explicit spread. |
| Spread radius | Fourth length | -100 to 100 px | Positive enlarges the shadow shape before blur; negative contracts it and can hide the shadow entirely. |
| Color | Hex input | Six-digit hex such as #3366CC | Channels are converted to decimal rgba components before serialization. |
| Opacity | Alpha channel | 0 to 100% | Serialized as a decimal alpha rounded to at most three places; 0% keeps the shadow syntactically present but invisible. |
| Inset | Keyword | On or off | Switches between an outer drop shadow and a shadow drawn inside the border edge. |
The color step is the one piece worth tracing because the tool never sends a hex string into the declaration. The six-digit hex is split into three byte pairs, each pair is read as a hexadecimal number, and each number is then written in decimal inside rgba(). The opacity slider adds the alpha component, and the final alpha is rounded to at most three decimal places. Take #3366CC at 40% opacity: the red channel is 0x33, which is 51 in decimal; the green channel is 0x66, which is 102; the blue channel is 0xCC, which is 204; and 40% converts directly to an alpha of 0.4. The serialized color is therefore rgba(51, 102, 204, 0.4), not #3366CC66 and not hsla(...). That single substitution is the only numeric work the tool performs; everything else is a direct pass-through of the values you set.
Outer Shadow vs Inset: Picking the Right Direction
The same six controls behave differently when you flip the inset option, because an inset shadow is drawn inside the border edge instead of behind the element. Positive offsets no longer push the shadow down and right of the box; they push the visible inner shadow up and left, so the perceived light source flips. A negative horizontal offset that moved an outer shadow to the left now moves an inner shadow toward the right inside the box. Most readers find this counterintuitive the first time, which is exactly why a live preview is more reliable than reasoning about it from memory.
| Use case | Shadow direction | Typical control choices |
|---|---|---|
| Card or panel lifted off the page | Outer | Small positive offsets, blur larger than the offsets, low opacity, zero or small positive spread. |
| Pressed button or recessed input | Inset | Small offsets in the direction of the simulated light, low opacity, modest blur, zero or small negative spread. |
| Subtle inner highlight on a hero block | Inset | Negative offsets toward the light source, very low opacity, low blur, zero spread. |
| Floating modal over a dimmed backdrop | Outer | Larger offsets and blur, slightly higher opacity, positive spread to deepen the footprint. |
Real components rarely need both effects on the same layer. If you find yourself wanting a card that is partly lifted and partly recessed, the spec allows multiple comma-separated shadows, but combining and ordering those layers is intentionally outside this single-layer generator — the page produces one layer at a time so each value is unambiguous and the declaration stays auditable.
Generate, Inspect, and Copy a CSS Box Shadow
The workflow is short on purpose: set values, watch the preview, read the declaration, copy, test in the real component. The numbered steps below mirror the order in which the generator is meant to be used.
- Open the CSS Box Shadow Generator in your browser; no file upload, account, or network call is required to render the preview.
- Adjust the horizontal and vertical offsets, blur, spread, color, opacity, and the inset option within the displayed limits until the sample card matches the depth you want.
- Inspect the sample card and read the exact generated declaration displayed directly below it; that string is the only thing the tool will copy.
- Paste the copied CSS into the intended selector in your stylesheet and remove any older box-shadow declarations you want to replace.
- Test the real component across light and dark themes, multiple sizes, focus and disabled states, and the browsers your audience actually uses.
If the copied string ends with rgba(0, 0, 0, 0), you have set opacity to 0 and the shadow is still syntactically present — that is intentional, not a bug. If a declaration renders nothing at all but the preview looked correct, suspect a parent with overflow: hidden, a transformed ancestor, or a stacking context that clips the shadow before it reaches the viewport.
What the Generator Intentionally Does Not Do
Knowing the boundaries of the tool matters as much as knowing what it produces. The generator creates one bounded shadow layer, not comma-separated stacks. It writes the current unprefixed box-shadow property only and never emits -webkit-box-shadow or -moz-box-shadow; modern browsers generally support the unprefixed form, and the tool does not run an autoprefixer or detect browser targets. It does not generate text-shadow, filter: drop-shadow(), Tailwind classes, CSS custom properties, design-system tokens, or animation keyframes. If you need any of those, the declaration is still a valid building block, but you will be assembling it into a larger rule yourself.
Browser rendering can also vary slightly with pixel density, transforms, zoom, compositing, and the shape of the element, so a declaration that looks perfect on a square sample card may look slightly different on a tall button or a wide hero panel. Treat the preview as a precise model of what the spec will compute, not as a guarantee of what every browser will paint in every context.
Sanity-Check the Copied CSS in Real Components
A shadow that looks balanced on a sample card can fail in production for reasons that have nothing to do with the values you chose. A dramatic shadow can reduce clarity by competing with the content, make a component look detached from its surroundings, create false visual hierarchy, or perform poorly over complex photographic backgrounds. Check contrast in light and dark themes; check disabled and focus states so a focus ring is not absorbed by an outer shadow; check high-contrast settings and reduced-transparency preferences where they apply. A shadow should reinforce structure rather than carry essential meaning alone — never encode state, severity, or required action only through a box-shadow value.
For reliable results, start with modest offsets, a blur larger than the offset, zero or small spread, and low opacity. Preview the declaration on a background similar to the destination, copy the CSS, place it in the intended rule, and inspect the real element at multiple sizes. If you want a checklist you can paste into a code comment while iterating, the Box Shadow Generator Cheat Sheet: Parameters and Recipes covers the same ranges and adds ready-made starting points for elevation levels. The generator does not modify project files and does not remember settings after a reload, so the rule you actually ship is the one you committed to your stylesheet.
For a deeper look, see How to Make Nice CSS Buttons With a Visual Workbench.