parse-css-color
parse-css-color turns a CSS color string into a small object with a color-space label, three numeric channel values, and a separate alpha value. Version 0.2.1 understands short and long hex with optional alpha, legacy comma and modern space syntax for rgb() and hsl(), percentage channels, degree, radian, and turn hue units, named CSS colors, and transparent. Invalid or unsupported input returns null instead of throwing, which makes it useful at validation boundaries and in color-picker plumbing.
A useful narrow parser when hex, RGB, HSL, and named colors are the complete input contract. Skip it for modern CSS color functions, strict range validation, or any workflow that also needs conversion and manipulation.
Use it if
- You need to validate user-supplied hex, rgb(), hsl(), named-color, or transparent strings without touching the DOM
- You want a tiny parser result shaped as { type, values, alpha } and will perform conversion or formatting elsewhere
- Your code must accept both comma-separated CSS Color Level 3 syntax and space-with-slash Level 4 syntax
- You need the same parser in CommonJS, ESM, or a direct browser script
- You need currentColor, inherit, CSS variables, calc(), color(), lab(), lch(), oklab(), oklch(), or color-mix(); the README lists currentColor and inherit as unsupported and the regex set only covers hex, RGB, HSL, keywords, and transparent
- You need color conversion or manipulation: HSL input stays HSL, RGB input stays RGB, and the package has no lighten, mix, contrast, or serialization methods
- You need strict range rejection: the implementation clamps out-of-range RGB, saturation, lightness, and alpha values instead of returning null, so rgb(500 -100 0) becomes [255, 0, 0]
- You need whitespace-tolerant form input: the tests explicitly expect leading or trailing spaces around transparent to fail, and the parser does not trim its argument
- You want a project with frequent releases and broad maintainer activity: 0.2.1 was published in April 2022, GitHub reports the last push in August 2023, and the repository has 15 stars
Setup reality
npm install parse-css-color is the whole installation. There are no peer dependencies, native builds, environment variables, or configuration files. The package publishes CommonJS, ESM, and browser bundles, plus a declaration file, so require('parse-css-color'), an ESM default import, and a script-tag global are all documented paths. The surprises are semantic. The parser does not normalize every result to RGB: an hsl() input returns type 'hsl' with hue, saturation, and lightness values, while hex, rgb(), keywords, and transparent return type 'rgb'. Alpha is always separate from values. Invalid input and non-string input return null, so destructuring without a guard can throw in your own code. The parser does not trim; trim form values yourself if surrounding whitespace should be accepted. Numeric channels are intentionally forgiving: RGB values are rounded and clamped to 0 through 255, saturation and lightness to 0 through 100, and alpha to 0 through 1. Mixed percentage and numeric RGB channels are rejected rather than normalized. Hue in degrees is not wrapped to 0 through 359, so a negative or greater-than-360 degree value can come back unchanged, while radians are converted and rounded. The TypeScript result says type is a general string rather than the narrower 'rgb' | 'hsl', and the package exposes no conversion or formatter. If downstream code needs one canonical color space, add that conversion explicitly or choose a fuller color library.
Patterns
Parse short and long hexadecimal colorsparse-hex
import parseCssColor from 'parse-css-color';
console.log(parseCssColor('#0af'));
// { type: 'rgb', values: [0, 170, 255], alpha: 1 }
console.log(parseCssColor('#00aaff80'));
// { type: 'rgb', values: [0, 170, 255], alpha: 0.5019607843137255 }Four-digit and eight-digit hex treat the last component as alpha. The returned alpha is a 0 through 1 number, not the original byte.
Guard the null result before destructuringguard-invalid-input
const parsed = parseCssColor(userInput);
if (parsed === null) {
return { ok: false, message: 'Enter a supported CSS color' };
}
const { type, values, alpha } = parsed;Invalid syntax, unsupported keywords, and non-string values return null. The parser does not throw its own validation error.
Trim a form value before parsingtrim-form-input
const raw = colorInput.value;
const parsed = parseCssColor(raw.trim());
if (!parsed) colorInput.setCustomValidity('Invalid color');The test suite expects ' transparent' and 'transparent ' to fail. Trim only when surrounding whitespace is acceptable in your input contract.
Parse modern RGB syntax with alphaparse-modern-rgb
const color = parseCssColor('rgb(255 0 153 / 20%)');
// { type: 'rgb', values: [255, 0, 153], alpha: 0.2 }All three RGB channels must use numbers or all three must use percentages. Mixed numeric and percentage channels return null.
Convert percentage RGB channels to bytesparse-percentage-rgb
const color = parseCssColor('rgb(41.2% 69.88% 96.64%)');
// { type: 'rgb', values: [105, 178, 246], alpha: 1 }Percentage channels are multiplied by 255 and rounded to integers. This can lose the original percentage precision.
Parse HSL hue unitsparse-hsl-units
parseCssColor('hsl(.75turn 60% 70% / 50%)');
// { type: 'hsl', values: [270, 60, 70], alpha: 0.5 }
parseCssColor('hsl(4.71239rad 60% 70%)');
// { type: 'hsl', values: [270, 60, 70], alpha: 1 }Radians and turns are converted to degrees. HSL results are not converted to RGB, so branch on type downstream.
Parse a named CSS colorparse-named-color
const color = parseCssColor('RebeccaPurple');
// { type: 'rgb', values: [102, 51, 153], alpha: 1 }Named-color lookup is case-insensitive and comes from color-name. System colors and misspelled names return null.
Handle the transparent keywordparse-transparent
const color = parseCssColor('transparent');
// { type: 'rgb', values: [0, 0, 0], alpha: 0 }transparent is represented as transparent black. Do not preserve its RGB channels as meaningful color information when alpha is zero.
Reject CSS-wide and context-dependent valuesdetect-unsupported-css-values
for (const value of ['currentColor', 'inherit', 'var(--brand)', 'oklch(60% .2 20)']) {
if (parseCssColor(value) === null) {
console.log('not handled:', value);
}
}The package supports literal hex, RGB, HSL, named colors, and transparent only. It cannot resolve values that depend on CSS context.
Account for clamped channel valuesobserve-channel-clamping
const color = parseCssColor('rgb(500 -100 12.6 / 200%)');
// { type: 'rgb', values: [255, 0, 13], alpha: 1 }Out-of-range numeric channels are clamped and RGB fractions are rounded. If out-of-range input must be invalid, validate before parsing.
Narrow the TypeScript resultnarrow-typescript-result
import parseCssColor, { Result } from 'parse-css-color';
function readColor(input: string): Result {
const result = parseCssColor(input);
if (!result) throw new TypeError('Unsupported CSS color');
return result;
}The bundled declaration types result.type as string rather than 'rgb' | 'hsl', so TypeScript cannot provide exhaustive model checking without your own narrower type.
Load the CommonJS builduse-commonjs
const parseCssColor = require('parse-css-color');
const parsed = parseCssColor('rgba(255, 0, 0, 0.5)');
console.log(parsed.alpha);The package's main field points to dist/index.cjs.js. Its module field provides the ESM build used by compatible bundlers.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| colord | npm | You want parsing plus conversion, formatting, manipulation, and plugins in a small modern package |
| color-string | npm | You want focused CSS color parsing and string generation with more model-aware output |
| color | npm | You need a fluent API for converting, mixing, lightening, and calculating contrast |
| tinycolor2 | npm | You maintain older browser code that already uses TinyColor's mature manipulation API |