CSS value parsing, color theory, and unit conversion. Typed values with units—deg, px, rem, oklch()—the CSS value vocabulary.
- Parse any CSS value: lengths, angles, times, colors,
calc(),var(), gradients, transforms - CSS Color Level 4 support:
color(),color-mix(), relative color syntax - 15 color spaces: RGB, HSL, HSV, HWB, Lab, LCh, OKLab, OKLCh, XYZ, Kelvin, sRGB-linear, Display P3, Adobe RGB, ProPhoto RGB, Rec. 2020
- Color space conversion via XYZ hub with analytical gamut mapping (Ottosson's algorithm)
- Color quantization: OKLab-native palette extraction (MMCQ + k-means++) with chroma-weighted clustering and JND deduplication
- CSS math functions:
calc(),min(),max(),clamp(), trig, exponential - 30+ easing functions: cubic-bezier, stepped, linear(), bounce, sine, expo
- 2D/3D matrix decomposition with quaternion slerp interpolation
- Normalize, interpolate, and convert between units
npm install @mkbabb/value.jsimport {
parseCSSValue,
parseCSSColor,
ValueUnit,
FunctionValue,
} from "@mkbabb/value.js";npm run build # library → dist/value.js + value.cjs + value.d.ts
npm run gh-pages # demo → dist/
npm run dev # dev server (Vite default port)
npm test # vitest (1387 tests)
npm run test:e2e # playwright (desktop + mobile)src/
├── index.ts # barrel exports (~200 symbols)
├── math.ts # lerp, bezier, clamp, scale, deCasteljau
├── easing.ts # CSS timing functions (cubic-bezier, stepped, linear())
├── utils.ts # clone, memoize, debounce, RAF, case conversion
├── parsing/ # @mkbabb/parse-that combinators for CSS values
│ ├── index.ts # parseCSSValue, gradients, transforms, var()
│ ├── units.ts # length, angle, time, frequency, resolution, flex, %
│ ├── color.ts # 15 spaces, hex, named, color-mix(), relative syntax
│ ├── math.ts # calc() AST, min/max/clamp, trig, exp
│ ├── utils.ts # istring, number, none, tryParse helpers
│ └── grammars/ # BBNF spec grammars (used in equivalence tests)
├── units/ # core value classes + unit definitions
│ ├── index.ts # ValueUnit, FunctionValue, ValueArray
│ ├── constants.ts # unit arrays, 630+ CSS property names
│ ├── utils.ts # unit conversion (px, deg, ms, Hz, dpi)
│ ├── normalize.ts # value normalization + interpolation setup
│ └── color/ # 15 color spaces, conversion, gamut mapping
│ ├── index.ts # Color<T> base + space classes
│ ├── constants.ts # ranges, matrices, white points, named colors
│ ├── matrix.ts # Vec3/Mat3 (row-major, replaces gl-matrix)
│ ├── utils.ts # conversions via XYZ, mixColors, gamutMap
│ ├── normalize.ts # color normalization to [0,1], space conversion
│ ├── gamut.ts # Ottosson analytical sRGB gamut mapping
│ └── colorFilter.ts # CSS filter solver (SPSA)
├── quantize/ # image color quantization
│ ├── index.ts # quantizePixels, dominantColor (public API)
│ ├── cluster.ts # MMCQ median cut, k-means++, JND dedup
│ └── types.ts # QuantizeOptions, QuantizedColor
└── transform/
└── decompose.ts # 2D/3D matrix decomposition, quaternion slerp
All conversions route through the XYZ D65 hub, enabling any-to-any conversion. Perceptual spaces (OKLab, Lab) use D50 natively with Bradford chromatic adaptation where needed.
Each color space is documented in assets/docs/, therein with historical context, component ranges, conversion functions, and practical applications.
Out-of-gamut colors are mapped using Björn Ottosson's analytical sRGB algorithm: a polynomial initial guess refined by a single Halley's method step (cubic convergence). Significantly faster than CSS Color 4's iterative binary search. Hue is preserved exactly; an adaptive L0 formula blends between chroma reduction and mid-gray anchoring.
See docs/colors/gamut-mapping.md for the full treatment.
quantizePixels() extracts a perceptual palette from raw image data. The pipeline operates natively in OKLab—MMCQ pre-clustering, k-means++ with chroma-weighted distance, JND deduplication.
import { quantizePixels, dominantColor } from "@mkbabb/value.js";
const palette = quantizePixels(pixels, width, height, { k: 6 });
const dominant = dominantColor(pixels, width, height);See docs/colors/quantization.md for the full pipeline.
30+ timing functions covering the CSS <easing-function> grammar plus bounce and back. CSSCubicBezier solves via Newton-Raphson with bisection fallback; cssLinear() implements CSS Easing Level 2 piecewise-linear with gap filling per spec; stepped easings support all four jump terms.
CSS matrix() and matrix3d() decomposition per the CSSOM View and CSS Transforms specs. 3D uses Gram-Schmidt orthogonalization + quaternion extraction. slerp for rotation interpolation. interpolateDecomposed() for full transform blending.
- Ottosson, B. (2020). A perceptual color space for image processing. — OKLab: the perceptual color space used for
color-mix()and gamut mapping. - Ottosson, B. (2021). sRGB gamut clipping. — Analytical gamut mapping algorithm (cubic boundary + Halley's method).
- Atkins Jr., T., Lilley, C., & Verou, L. (2025). CSS Color Module Level 4. W3C CRD. — The spec governing all CSS color functions.
- CSS Filter Effects Module Level 1. W3C. —
feColorMatrix; basis for the CSS filter solver. - Lindbloom, B. XYZ to Correlated Color Temperature. — CCT conversion reference.
@mkbabb/parse-that— Parser combinators powering the CSS value grammar.
See docs/colors/theory.md for the full bibliography.