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
0rather than0px, 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 barergb()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:
| Case | Expected output |
|---|---|
| Single layer, 4/4/8/0, black at 25% alpha | 4px 4px 8px 0 rgba(0,0,0,0.25) |
| Same layer with inset set | inset 2px 2px 5px 0 … |
| Black at alpha 0.25 | rgba(0,0,0,0.25) |
| Two layers | Joined with ", " |
| Negative offset and spread | -4px -6px 10px -3px … |
| Alpha 1 | rgba(164,103,233,1) | — never bare
| 3-digit hex shorthand | #0a7 expands to [0,170,119] |
| Negative blur input | Clamped to 0 in the output |
| Empty layer list | none |
| Long-shadow generator, 5 steps | 5 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.