mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmUtilsupdated 08 Aug 2026

@colordx/core

@colordx/core is a zero-dependency JavaScript and TypeScript library for parsing, converting, comparing, and changing colors. Its core handles hex, RGB, HSL, OKLab, and OKLCH, including explicit sRGB gamut checks and mapping. Optional subpath plugins add named colors, accessibility checks, mixing and palettes, minification, CIE Lab/LCH, Display-P3, Rec.2020, A98 RGB, ProPhoto RGB, CMYK, HSV, and HWB. Instances are immutable, and low-allocation functions cover canvas and visualization hot loops.

Verdict

An impressive modern color engine for OKLCH, gamut-aware design tools, and high-volume conversion. For routine hex and RGB work, its fast-moving majors and plugin-wide surface are more machinery than most teams need; colord is the calmer default.

API stability2/5The immutable factory and conversion names are coherent in 5.5.0, but the release history is too young to call settled: npm records four major jumps from 2.0.0 through 5.0.0 between March 26 and March 29, 2026. Subsequent 5.x releases added more spaces and low-level functions quickly. Semantic major numbers make the changes visible, yet applications should pin and review rather than assume a broad range is harmless.
Docs4/5The README is exceptionally broad, with exact inputs and outputs for core formats, plugin registration, gamut clipping versus mapping, precision, relative operations, accessibility, wide gamuts, and allocation-free loops. The colordx.dev playground makes visual behavior testable. The cost is density and some drift: the roadmap still lists A98 and ProPhoto parsing as future work even though 5.5.0 added those plugins and earlier sections document them.
Maintenance5/5Version 5.5.0 was published on June 24, 2026, the repository was pushed the following day, and the latest commits add A98 and ProPhoto support plus playground improvements. GitHub reports zero open issues and pull requests, CI is linked from the README, and the project is actively used by cssnano. This is strong activity, though much of the API is still new enough that maintenance and invention are happening together.
Ecosystem4/5The package recorded 4,035,494 downloads for July 31 through August 6, 2026 and the README identifies cssnano and oklch-picker as users. It covers an unusually wide set of modern spaces while offering ESM, CommonJS, and TypeScript. The direct community is still small at 109 GitHub stars, and the plugin catalog is maintained inside one repository rather than through a broad third-party extension ecosystem.

Use it if

  • You need first-class OKLCH and OKLab input, output, manipulation, and sRGB gamut mapping rather than treating them as conversion afterthoughts
  • You want one typed color API that can opt into Display-P3, Rec.2020, A98 RGB, ProPhoto RGB, Lab, LCH, accessibility, palettes, and minification through subpath plugins
  • You process color in canvas, charts, pickers, or image-like loops and can use the documented *Into functions to reuse output buffers
  • You need zero runtime dependencies and dual ESM/CommonJS exports while keeping less common color spaces out of the base setup
Skip it if

Setup reality

The base install has no dependencies, native code, credentials, or configuration file. Import colordx from @colordx/core and it can immediately parse hex, RGB, HSL, OKLab, and OKLCH. Everything else requires deliberate plugin registration. Import extend plus the plugin's default export, call extend([plugin]) once in a bootstrap module, and ensure that module runs before code parses that color space or calls augmented methods. Registration changes the shared Colordx surface, so scattered feature modules that register plugins as side effects make tests and bundles harder to reason about. Import plugin paths directly so a bundler can omit unused code. The package publishes both ESM and CommonJS plus matching declarations. Its unit conventions are easy to mix up: RGB objects use 0 to 255 channels, HSL saturation and lightness use 0 to 100, OKLCH lightness uses 0 to 1, alpha uses 0 to 1, and wide-gamut RGB plugin channels use 0 to 1. CIE Lab and OKLab share l/a/b-shaped objects, while LCH and OKLCH share l/c/h, so plugin inputs need the documented colorSpace discriminant. Parsing failure does not replace application validation; check isValid() before conversion when input is user-controlled. Objects are immutable, so every manipulation returns a new instance and ignoring the result does nothing. Out-of-gamut OKLCH and OKLab values remain stored unclamped, but toHex and toRgbString clip at output to match browser rendering. Use mapSrgb when authoring palettes that should preserve hue, and clampSrgb when you want an object describing clipped screen output. Display-P3 and other wide-gamut strings also depend on actual browser and display support. For tight loops, the *Into variants require caller-owned output arrays; functions producing both linear and gamma output require two distinct buffers. Finally, version pinning deserves attention: the package is active and typed, but its March 2026 history contains several rapid major releases, so read changelogs before relaxing a major range.

Patterns

Validate a user-supplied colorvalidate-color-input

import { colordx } from '@colordx/core';

const color = colordx(input);
if (!color.isValid()) {
  throw new TypeError('Unsupported color');
}
const normalized = color.toHex();

Validate before conversion when input is untrusted. Browser-valid CSS Color 4 or 5 syntax may still be outside the library's current parsers.

Convert one color to common formatsconvert-color-formats

const color = colordx('#3d7a9f');

color.toRgb();         // { r, g, b, alpha }
color.toHslString();   // CSS Color 4 space syntax
color.toOklch();       // { l, c, h, alpha }
color.toNumber();      // integer form

Conversion methods apply format-specific default precision. Pass a precision argument when serialized decimals form part of a stable output contract.

Emit comma-separated legacy RGBwrite-legacy-rgb

const modern = colordx({ r: 255, g: 0, b: 0, alpha: 0.5 }).toRgbString();
const legacy = colordx({ r: 255, g: 0, b: 0, alpha: 0.5 }).toRgbString({ legacy: true });
// modern: rgb(255 0 0 / 0.5)
// legacy: rgba(255, 0, 0, 0.5)

Legacy output switches to rgba() when alpha is below one. Use it only for consumers that cannot accept current CSS space and slash syntax.

Chain immutable color adjustmentschain-immutable-changes

const base = colordx('#3d7a9f');
const variant = base
  .lighten(0.1)
  .saturate(0.05)
  .rotate(20)
  .alpha(0.8);

console.log(base.toHex(), variant.toHex());

Every manipulation returns a new Colordx instance. Calling base.lighten(0.1) without storing or chaining the result leaves base unchanged.

Choose absolute or relative lighteninglighten-relatively

const color = colordx('#1a0000');
const absolute = color.lighten(0.1);
const relative = color.lighten(0.1, { relative: true });

Absolute mode adds ten percentage points. Relative mode adds ten percent of the current lightness, which produces a much smaller change on dark colors.

Map an OKLCH color into sRGBmap-srgb-gamut

import { colordx, inGamutSrgb } from '@colordx/core';

const authored = colordx('oklch(0.5 0.4 180)');
if (!inGamutSrgb(authored.toOklchString())) {
  const mapped = authored.mapSrgb();
  console.log(mapped.toHex());
}

toHex alone clips channels and may move hue. mapSrgb reduces chroma using the documented CSS Color 4 strategy to preserve lightness and hue more closely.

Register and serialize Display-P3enable-display-p3

import { colordx, extend } from '@colordx/core';
import p3, { inGamutP3 } from '@colordx/core/plugins/p3';

extend([p3]);

const color = colordx('color(display-p3 0.92 0.2 0.14)');
console.log(color.toP3String(), inGamutP3(color.toOklchString()));

Register the plugin once before parsing P3 strings or calling instance P3 methods. A valid P3 value can still be clipped by a display that only supports sRGB.

Mix colors in Oklabmix-perceptually

import { colordx, extend } from '@colordx/core';
import mix from '@colordx/core/plugins/mix';

extend([mix]);

const midpoint = colordx('#000').mixOklab('#fff', 0.5).toHex();

The plain mix method uses sRGB. Use mixOklab for perceptual interpolation; tints, shades, and tones still use the plugin's sRGB mix behavior.

Check WCAG 2.x text contrastcheck-text-contrast

import { colordx, extend } from '@colordx/core';
import a11y from '@colordx/core/plugins/a11y';

extend([a11y]);

const text = colordx('#333');
const passesAA = text.isReadable('#fff');
const score = text.readableScore('#fff');

The default is AA normal text. Pass level and size options for other policies, and evaluate non-color requirements separately.

Enable CSS named colorsparse-named-colors

import { colordx, extend } from '@colordx/core';
import names from '@colordx/core/plugins/names';

extend([names]);

colordx('rebeccapurple').toHex(); // #663399
colordx('#ff0000').toName();      // red

Color names are not part of the base parser. toName returns undefined when no exact CSS name exists unless closest matching is requested.

Choose the shortest CSS representationminify-css-color

import { colordx, extend } from '@colordx/core';
import minify from '@colordx/core/plugins/minify';
import names from '@colordx/core/plugins/names';

extend([minify, names]);

const shortest = colordx('#ff0000').minify({ name: true }); // red

The name option depends on the names plugin. The minifier compares valid candidates and preserves precision rather than blindly rounding HSL.

Avoid allocations in a pixel loopreuse-conversion-buffer

import { oklchToRgbChannelsInto } from '@colordx/core';

const rgb = new Float64Array(3);
for (const [l, c, h] of pixels) {
  oklchToRgbChannelsInto(rgb, l, c, h);
  output.push(
    Math.max(0, Math.min(255, Math.round(rgb[0] * 255))),
    Math.max(0, Math.min(255, Math.round(rgb[1] * 255))),
    Math.max(0, Math.min(255, Math.round(rgb[2] * 255))),
  );
}

Reuse one Float64Array only after profiling shows allocation pressure. Channel helpers may return out-of-gamut values, so clamp before byte conversion.

Alternatives

PackageRegistryPick it when
colordnpmChoose it for a compact, mature core with familiar RGB/HSL manipulation and opt-in plugins
culorinpmChoose it when broad color-science coverage, interpolation modes, filters, and functional composition matter more than a chain API
chroma-jsnpmChoose it for established data-visualization scales, domain mapping, bezier palettes, and a long-used API
tinycolor2npmChoose it for legacy projects that only need common web colors and value compatibility over modern wide-gamut support