About this box-shadow generator

A small, dependency-free tool for one job: turning slider positions into a correct box-shadow declaration you can paste straight into a stylesheet. No account, no upload, and nothing you configure is ever recorded.

Why it exists

box-shadow is one of the more fiddly CSS properties to hand-write, because it packs six pieces of information into one comma-separated line and the order matters: offsets, then optional blur, then optional spread, then colour, with an optional inset keyword thrown in wherever the author remembers to add it. Realistic-looking shadows almost always need two or three of these stacked, which multiplies the arithmetic. This tool removes the arithmetic: you move a slider, the number updates, the preview updates, and the exact line of CSS updates with it.

How the CSS is assembled

Each layer is held as a small object — offset-x, offset-y, blur, spread, a hex colour, an alpha value and an inset flag — and turned into one box-shadow entry by a single pure function:

  • Lengths round to the nearest pixel. A value of exactly zero is written bare as 0 rather than 0px, matching how a browser's own computed-style serialiser writes it.
  • Blur never goes negative. CSS itself does not allow a negative blur radius, so the value is floored at 0 before formatting, even if a slider is somehow dragged past its stated range.
  • Colour is always written as rgba(r, g, b, a), even when alpha is 1 — one consistent syntax rather than switching to bare rgb() at full opacity.
  • inset, when set, is written first, which is the more common convention and reads unambiguously either way per the CSS specification.
  • Multiple layers join with ", ", in the order they appear in the layer list — which is also the order they are painted, front layer first.

How it was verified

The assembly function is pure — it takes a layer object and returns a string, with no DOM involved — so it is exported for Node and checked with a small assertion script before anything ships:

— never bare rgb()
Verification cases and their expected output
CaseExpected output
Single layer, 4/4/8/0, black at 25% alpha4px 4px 8px 0 rgba(0,0,0,0.25)
Same layer with inset setinset 2px 2px 5px 0 …
Black at alpha 0.25rgba(0,0,0,0.25)
Two layersJoined with ", "
Negative offset and spread-4px -6px 10px -3px …
Alpha 1rgba(164,103,233,1)
3-digit hex shorthand#0a7 expands to [0,170,119]
Negative blur inputClamped to 0 in the output
Empty layer listnone
Long-shadow generator, 5 steps5 diagonal, no-blur layers, x and y both incrementing by 1

Every case above passed under Node before this page shipped. You can re-run the same checks yourself in a browser console on any page of this tool: the pure functions are exposed on module.exports for Node and are also reachable by opening box-shadow.js directly, since the same file guards its DOM-wiring half behind a typeof document check.

How the site is built

  • Static HTML, one stylesheet, one script. No framework, no build step, no bundler.
  • The generator needs nothing from the network. No CDN framework, no web font, no remote image; the favicon and header mark are inline SVG. Once the page has loaded, it keeps working offline.
  • System font stack — your operating system's own UI font, so nothing has to download and nothing shifts as the page loads.
  • What you configure never leaves your device. Layer values live in this tab's memory only; nothing is uploaded, and the Copy button writes straight to your own clipboard.
  • Dark mode follows your system setting via prefers-color-scheme.

The site's own contrast

Body text measures 15.69:1 against this page's dark background and 16.74:1 in light mode; the muted secondary text used for labels and captions is 8.24:1 dark and 6.48:1 light — both figures shared across every tool on this site, since they come from the same base stylesheet. This tool's own violet accent — used for links, the active nav item and the focus ring — measures 5.13:1 on the page background and 4.73:1 on a raised panel in dark mode, and 11.40:1 and 11.89:1 in the same two places in light mode; every figure clears the 4.5:1 floor for normal text with room to spare. Every slider, number field, checkbox and button is reachable and operable by keyboard, and the copy confirmation is announced through a polite live region for screen reader users.

If you find a control on this page that fails that bar, that is a bug worth reporting — see contact.

Scope and honesty about limits

This tool produces box-shadow CSS only. It does not generate filter: drop-shadow(), does not export SVG or image assets, and does not simulate how expensive a given shadow will be to paint on your actual page — that depends on your element count, your animations and the visitor's device, none of which a static generator can see. The preset elevation and pressed-state values are a reasonable starting point, not a guarantee that they match any particular design system pixel-for-pixel; treat them as a base to tune, not a spec to match exactly.