JavaScript Box Shadow Parser
Reading CSS box-shadow values in JavaScript can be complex because they combine offsets, blur, spread, colors, and optional inset values. JavaScript Box Shadow Parser converts any box-shadow value into structured layer objects and can also convert those objects back into valid CSS with stringify().
Built for real-world CSS, it supports multiple shadow layers, rgba(), hsl(), modern color syntax, hex colors, named colors, and inset values. With zero dependencies and TypeScript support, it integrates easily into shadow generators, design tools, style editors, and CSS-to-JavaScript workflows in both browsers and Node.js.
Table of Contents
What is JavaScript Box Shadow Parser?
JavaScript Box Shadow Parser is a zero-dependency library that converts CSS box-shadow values into structured JavaScript layer objects - and back again with stringify(). It supports multi-layer shadows, every CSS color format, and the inset keyword, and runs in both the browser and Node.js.
Features
css-box-shadow-parser Features
- Multi-layer parsing - splits comma-separated shadows into one object per layer.
- Full declaration support - accepts raw values or complete
box-shadow: ...;declarations and strips the property name and semicolon automatically. - All color formats - 3/4/6/8-digit hex,
rgb(),rgba(),hsl(),hsla(), named colors,transparent, andcurrentcolor. - Modern and legacy syntax - handles both comma syntax and the space/slash syntax such as
rgb(0 0 0 / 0.5)andhsl(270 80% 50% / 0.6). - Smart comma splitting - commas inside color functions are never mistaken for layer separators.
- Resolved hex + alpha - every layer returns a normalized 6-digit hex plus a separate alpha value from 0 to 1.
- Inset detection - recognizes the
insetkeyword wherever it appears in the value. - Negative offsets and spread - parses negative x, y, and spread values correctly.
- Graceful handling - CSS-wide keywords like
none,initial, andinheritreturn an empty array. - Zero dependencies - small UMD bundle that works in the browser and Node.js.
Demo
Pick a shadow type from the dropdown to see it parsed in real time. The selected CSS box-shadow value is passed to parse() and the resulting layer objects are shown below, along with a live preview box.
Add box shadow code:
Parsed output:
[
{
"inset": false,
"x": 4,
"y": 4,
"blur": 10,
"spread": 0,
"color": "rgba(0,0,0,0.4)",
"alpha": 0.4,
"hex": "#000000"
}
] Got the parsed objects? Click Back to CSS to run them through stringify() - the inverse of parse() - and rebuild a valid box-shadow string. This is the full round-trip: read a shadow, edit the values, and write it straight back to CSS.
box-shadow: 4px 4px 10px rgba(0,0,0,0.4); Links
Browse the source code on GitHub or grab the package from npm.
Install
Install the package from npm for use in Node.js or any bundler, or drop in the script from a CDN to use it directly in the browser with no build step.
NPM
npm install css-box-shadow-parser Browser Usage
<script src="https://unpkg.com/css-box-shadow-parser"></script>
<script>
const layers = BoxShadowParser.parse('4px 4px 10px rgba(0,0,0,0.4)');
console.log(layers);
// output
// [{"inset":false,"x":4,"y":4,"blur":10,"spread":0,"color":"rgba(0,0,0,0.4)","alpha":0.4,"hex":"#000000"}]
</script> Node.js Usage
const { parse, parseSingle, split } = require('css-box-shadow-parser');
// Single layer
parse('4px 4px 10px rgba(0,0,0,0.4)');
// Multi-layer
parse('0 1px 2px #0002, 0 4px 8px #0002');
// Full CSS declaration - strips "box-shadow:" and ";" automatically
parse('box-shadow: inset 0 2px 4px rgba(0,0,0,.24);');
// CSS keyword - returns empty array
parse('none'); // [] API
The library exposes three functions: parse() for full values, parseSingle() for one shadow token, and split() for tokenizing without parsing.
parse(shadow) - BoxShadowLayer[]
Parses a full box-shadow value, single or multi-layer. Accepts raw values or complete CSS declarations including the box-shadow: property name and trailing semicolon.
parse('0 2px 8px rgba(0,0,0,0.3)')
parse('box-shadow: inset 0 2px 4px rgba(0,0,0,.24);')
parse('0 1px 2px #0002, 0 4px 8px #0002') // multi-layer
parse('none') // [] parseSingle(token) - BoxShadowLayer | null
Parses a single shadow token. Returns null for invalid or empty input.
parseSingle('inset 0 2px 4px coral') split(shadow) - string[]
Splits a compound value on top-level commas without parsing. Commas inside rgba(), hsl() and other functions are correctly ignored.
split('4px 4px 0 red, inset 0 0 10px rgba(0,0,0,.5)')
// - ['4px 4px 0 red', 'inset 0 0 10px rgba(0,0,0,.5)'] stringify()
The inverse of parse(). Pass a single layer object or an array of layers and get back a valid CSS box-shadow string. Together, parse() and stringify() let you read a shadow, modify it in code, and write it straight back to CSS.
stringify(input) - string
Accepts a BoxShadowLayer object or an array of them. Numeric offsets are written with px (a value of 0 stays unitless), blur and spread are omitted when not needed, and the original color token is preserved when present - otherwise a color is rebuilt from hex and alpha.
// Round-trip: CSS -> objects -> CSS
const layers = parse('6px 6px 12px #b8b9be, -6px -6px 12px #ffffff');
stringify(layers);
// "6px 6px 12px #b8b9be, -6px -6px 12px #ffffff"
// Edit in between
layers[0].blur = 24;
stringify(layers);
// "6px 6px 24px #b8b9be, -6px -6px 12px #ffffff"
// Build a shadow from a plain object
stringify({ inset: false, x: 0, y: 8, blur: 24, spread: 0, hex: '#6c63ff', alpha: 0.4 });
// "0 8px 24px rgba(108, 99, 255, 0.4)"
// Single object also works
stringify({ inset: true, x: 2, y: 2, blur: 4, spread: 0, color: 'red' });
// "inset 2px 2px 4px red" Return Type
Each parsed layer is a plain object with the following shape. Offsets, blur, and spread are returned as numbers, color keeps the original token, and hex plus alpha give you a normalized color you can use anywhere.
| Property | Type | Description |
|---|---|---|
inset | boolean | true if the shadow uses inset |
x | number | Horizontal offset in px |
y | number | Vertical offset in px |
blur | number | Blur radius in px |
spread | number | Spread radius in px (can be negative) |
color | string | Original CSS color token |
alpha | number | Opacity 0–1 (extracted from color) |
hex | string | Resolved 6-digit hex (e.g. #663399) |
TypeScript Definitions
The package ships with built-in TypeScript definitions (index.d.ts), so you get full autocomplete and type checking with no @types install required.
import { parse, stringify, BoxShadowLayer } from 'css-box-shadow-parser';
const layers: BoxShadowLayer[] = parse('0 8px 24px rgba(0,0,0,0.4)');
const first: BoxShadowLayer = layers[0];
first.blur; // number
first.hex; // string
first.inset; // boolean
const css: string = stringify(layers); The exported BoxShadowLayer interface describes every field returned by parse() and parseSingle().
Examples
The examples below show the parsed output for common shadow patterns, from named colors and hex with alpha to inset and multi-layer shadows.
Named color
parse('0 0 28px 6px rebeccapurple')
// [{
// inset: false, x: 0, y: 0, blur: 28, spread: 6,
// color: 'rebeccapurple', alpha: 1, hex: '#663399'
// }]
8-digit hex with alpha
parse('0 8px 24px #00000066')
// [{
// inset: false, x: 0, y: 8, blur: 24, spread: 0,
// color: '#00000066', alpha: 0.4, hex: '#000000'
// }] HSL color
parse('0 6px 20px hsl(270 80% 50% / 0.6)')
// [{
// inset: false, x: 0, y: 6, blur: 20, spread: 0,
// color: 'hsl(270 80% 50% / 0.6)', alpha: 0.6, hex: '#8019e6'
// }] Inset shadow
parse('inset 0 2px 4px rgba(0,0,0,0.24)')
// [{
// inset: true, x: 0, y: 2, blur: 4, spread: 0,
// color: 'rgba(0,0,0,0.24)', alpha: 0.24, hex: '#000000'
// }] Multi-layer (neumorphic)
parse('6px 6px 12px #b8b9be, -6px -6px 12px #ffffff')
// [
// { inset: false, x: 6, y: 6, blur: 12, spread: 0, color: '#b8b9be', alpha: 1, hex: '#b8b9be' },
// { inset: false, x: -6, y: -6, blur: 12, spread: 0, color: '#ffffff', alpha: 1, hex: '#ffffff' }
// ] Split without parsing
split('4px 4px 0 red, inset 0 0 10px rgba(0,0,0,.5)')
// ['4px 4px 0 red', 'inset 0 0 10px rgba(0,0,0,.5)'] Supported Color Formats
Every color format allowed in a CSS box-shadow is recognized and resolved to a hex value with a separate alpha channel.
| Format | Example |
|---|---|
| 3-digit hex | #f00 |
| 4-digit hex + alpha | #f00a |
| 6-digit hex | #ff0000 |
| 8-digit hex + alpha | #ff000066 |
| rgb() comma | rgb(255, 0, 0) |
| rgb() space syntax | rgb(255 0 0) |
| rgba() comma + alpha | rgba(0, 0, 0, 0.5) |
| rgba() space / slash alpha | rgba(0 0 0 / 0.5) |
| hsl() comma | hsl(270, 80%, 50%) |
| hsl() space + slash alpha | hsl(270 80% 50% / 0.6) |
| hsl() deg unit | hsl(200deg 70% 50%) |
| hsla() comma + alpha | hsla(340, 82%, 52%, 0.7) |
| Named color | rebeccapurple, coral, etc. |
| transparent | alpha=0 |
| currentcolor | resolves to #000000 |
Use Cases
Anywhere you need to read, edit, or transform shadows programmatically:
- Shadow editors and generators - parse a pasted value into sliders and color pickers, then
stringify()the result back to CSS. - Design-token and theme tools - convert shadow declarations into JSON tokens for design systems.
- CSS-to-JS pipelines - feed shadow data into canvas, SVG, or React Native styling, which use separate shadow properties.
- Linters and visual diff tools - compare two shadows layer by layer instead of as raw strings.
- Color extraction - pull resolved hex and alpha values out of any shadow for previews or contrast checks.
- Migration scripts - normalize inconsistent shadow syntax across a large codebase.
Browser & Environment Support
The library is plain ES5-compatible JavaScript in a UMD wrapper, so it runs anywhere with no build step.
| Environment | Support |
|---|---|
| Chrome, Firefox, Safari, Edge | All modern versions |
| Node.js | 14 and above |
| Module systems | CommonJS, browser global, CDN script tag |
| TypeScript | Built-in type definitions |
| Dependencies | None |
Frequently Asked Questions (FAQ)
How do I parse a CSS box-shadow string in JavaScript?
Pass the value to parse(): BoxShadowParser.parse('4px 4px 10px rgba(0,0,0,0.4)'). It returns an array of layer objects, each with inset, x, y, blur, spread, color, alpha, and a resolved hex value. You can pass a raw value or a full box-shadow: ...; declaration.
Does it support multiple shadow layers?
Yes. Comma-separated shadows are split into one object per layer, and commas inside rgba() or hsl() functions are correctly ignored, so multi-layer values parse reliably.
What color formats are supported?
3-, 4-, 6-, and 8-digit hex, rgb(), rgba(), hsl(), hsla() in both comma and space/slash syntax, all named CSS colors, transparent, and currentcolor. Every color resolves to a 6-digit hex plus a separate alpha value.
Does it work in Node.js and the browser?
Yes. The library uses a UMD wrapper, so it works as a CommonJS module in Node.js (require('css-box-shadow-parser')) and as a global BoxShadowParser in the browser via a script tag or CDN.
Does the parser have any dependencies?
No. It is a zero-dependency library released under the MIT license, so you can use it freely in personal and commercial projects.
What happens with keywords like none or inherit?
CSS-wide keywords such as none, initial, inherit, and unset return an empty array, so you can safely call parse() on any computed style value.
License
Released under the MIT License - free to use in personal and commercial projects. See the LICENSE file on GitHub for full terms.
Related
Related links