v0.11.8 — MetricSpace + GenSpace

Your Colors Deserve
Better Math
Two Purpose-Built
Lab Spaces

You know the problem: blue-to-white gradients go purple. Dark palettes have muddy holes. Yellows look washed out. Helmlab fixes all of that.

GenSpace for generation. MetricSpace for measurement.
Same library, two pipelines optimized for different objectives.

Wins 66 out of 90 quality tests vs OKLab
66-9 vs OKLab on 90 benchmarks (15 ties)
$ pip install helmlab
$ npm install helmlab
The Problem

You've seen this before

You pick a vivid blue. You make a gradient to white. And the midpoint loses its punch — it fades out instead of staying blue. The difference is subtle, but once you see it, you can't unsee it.

OKLab (the current standard)

The midpoint (#8ba8ff) loses blue intensity — it fades toward a pale, washed-out periwinkle.

Helmlab

The midpoint (#649cff) holds stronger blue saturation through the transition.

Red to White
OKLab — similar warmth
Helmlab — very similar
Yellow to White
OKLab — slightly more saturated early
Helmlab — more linear fade
Teal to Black
OKLab — slightly compressed darks
Helmlab — smoother dark transition
Palettes

The dark hole problem

You generate a 50-950 scale from your brand color. But 700-800 looks like a black hole — the steps aren't even. That's because OKLab's lightness channel isn't actually uniform.

OKLab palettefrom #3b82f6

Notice the jump between 700 and 800. The dark end feels compressed.

Helmlab palettefrom #3b82f6

Every step looks evenly spaced. The dark end is smooth. 18x better lightness uniformity.

Try It

See it with your own colors

Pick two colors and compare the gradient. Then try the full playground for palettes and more.

See the Difference

Three color spaces, same endpoints. Notice the midpoint.

* Perceptually uniform via CIEDE2000 arc-length reparameterizationFull playground →
Use Cases

Built for the work you actually do

Design Systems

Generate a full 50-950 Tailwind-style scale from any brand color. Every step is perceptually even. Export to CSS variables, Tailwind config, or design tokens.

hl.semanticScale("#3b82f6")
Dark Mode

Dark gradients that don't turn muddy. 26% smoother in the dark range where OKLab struggles most. Your dark theme looks intentional, not accidental.

hl.adaptToMode("#3b82f6", "light", "dark")
Data Visualization

Categorical palettes with maximum separation. Your chart colors stay distinct even for colorblind users.

hl.palette_hues(lightness=0.6, steps=8)
Wide Gamut (P3)

Modern displays show colors outside sRGB. Helmlab maps them correctly — no ugly hue shifts when clipping P3 colors to sRGB.

hl.gamutMap("#ff0080", "srgb")
Honest

When to use something else

We could hide this. We won't. You deserve to know before choosing.

CSS-only gradients

If you need gradients in pure CSS without JavaScript, use oklch() — it's built into browsers.

Very subtle gray gradients

Gradients between nearly identical grays are 24% smoother in OKLab. It's our biggest weakness.

Green-blind accessibility

OKLab gives 43% better step distinction for deuteranopia palettes. Use it for CVD-critical designs.

HDR displays

For >1000 cd/m2 content, use Jzazbz. Helmlab is optimized for standard dynamic range.

Smallest possible bundle

OKLab is ~2KB. Helmlab is 11.6KB gzipped. If every kilobyte counts, OKLab is lighter.

Legacy CIE Lab workflows

Decades of industry hue naming is based on CIE Lab. If you need interop with those systems, stick with Lab.

Get Started

Ask your developer for three lines

One install, one import, one function call. Then hand the hex values to your design tokens.

// That's it. Really.
import { Helmlab } from 'helmlab';
const scale = new Helmlab().semanticScale('#3b82f6');

Common questions

Do I need to know color science?

No. Import Helmlab, give it a hex color, get better results back. The math is hidden.

Does it work with Tailwind / Figma / Tokens Studio?

Helmlab outputs hex values and CSS variables. It works with anything that accepts standard color formats. Tailwind config export is built in.

Why can't I just use oklch() in CSS?

You can! oklch() is great for CSS-only gradients. But if you're generating colors in JavaScript (design tokens, palette tools, theme generators), Helmlab gives visibly better results because it uses a richer perceptual model.

Is it free?

Yes. MIT licensed. Use it in any personal or commercial project.

How much does it add to my bundle?

11.6 KB gzipped, zero dependencies. About the same as a small icon set.

What if I need to match brand colors exactly?

Helmlab is exactly invertible. The same hex always produces the same Lab values, and vice versa. Zero rounding error.

Key Metrics

Numbers that speak for themselves

ColorBench: 90 metrics, 3,038 gradient pairs, 3 gamuts, float64 precision. Head-to-head vs OKLab.

22.48
STRESS score on COMBVD (3813 pairs)
23% better than CIEDE2000
66-9
90 metrics, 13 categories
Including 6-1 on independent 3rd-party datasets
360/360
sRGB + P3 valid cusp coverage
OKLab: 299/360 sRGB, 308/360 P3
18 x
Munsell Value: 0.16% vs 2.80%
Uniform L channel by construction
1.513
Blue-to-White midpoint G/R ratio
OKLab: 1.408 (purple-shifted)
10 -15
Achromatic purity (D65 C*)
1M times better than OKLab
Live Demo

Gradient Comparison

Helmlab vs OKLab vs CIE Lab — pick any two colors.

See the Difference

Three color spaces, same endpoints. Notice the midpoint.

* Perceptually uniform via CIEDE2000 arc-length reparameterizationFull playground →
Architecture

Two Spaces, One Library

GenSpace for creating colors, MetricSpace for measuring them. Same library, different pipelines optimized for different objectives.

GenSpace

For Generation

~35 parameters, depressed cubic transfer, CMA-ES optimized M1/M2 matrices, structural achromatic.

66-9 vs OKLab
360/360 sRGB cusps
0 deps 11.6KB gzip
Pipeline
XYZ M1 depcubic M2 enrich PW-L NC Lab
gradient() palette() semanticScale() gamutMap()
MetricSpace v21

For Measurement

72-parameter enriched pipeline with Bradford CAT, Helmholtz-Kohlrausch correction, pair-dependent SL/SC weighting.

22.48 STRESS
72 parameters
23% better than CIEDE2000
Pipeline
XYZ CAT M1 γ M2 hue H-K NC Lab
deltaE() fromHex() info() stress()
Recommended

When to Use Helmlab

Tasks where GenSpace or MetricSpace measurably outperforms alternatives.

Design System Palettes

Munsell Value CV: 0.16% vs OKLab 2.80%. 18x better lightness uniformity.

Gradient Interpolation

31% less max hue drift, 18% better cross-lightness CV. G/R=1.51 (OKLab: 1.41).

Gamut Mapping

360/360 cusps, 0 mono violations, cusp smoothness 0.072 (OKLab: 0.805). 11x smoother.

Data Visualization

Higher min pairwise delta-E (14.50 vs 14.34). Better perceptual distinctiveness.

Dark UI Themes

Dark gradient CV: 37.24% vs OKLab 47.28%. 26% better uniformity in L<0.4.

Color Animation

Frame-to-frame CV: 60.1% vs 62.1%. Fewer quantization artifacts in 8-bit.

Wide Gamut (P3, Rec.2020)

P3 cusps: 360/360 (OKLab: 308). Zero P3 mono violations (OKLab: 71).

Blue / Yellow Design

Blue G/R=1.513 (OKLab: 1.408). Yellow chroma 0.333 (OKLab: 0.211, +58%).

Honest

When NOT to Use Helmlab

We believe in honest recommendations. These tools are better for specific use cases.

Near-Achromatic Gradients

Use OKLab

Near-achromatic CV: OKLab 85.95% vs Helmlab 106.73%. 24% gap.

CVD Deutan Palettes

Use OKLab

Deutan min step delta-E: OKLab 0.157 vs Helmlab 0.110. 30% gap.

CSS oklch() Required

Use OKLab

oklch() is in CSS Color Level 4. Zero bundle cost.

HDR / PQ Content

Use Jzazbz

Perceptual quantization for luminance >1000 cd/m2. Untested territory.

Minimal Bundle Size

Use OKLab

OKLab: ~2KB. Helmlab: 11.6KB gzipped. 6x larger.

CIE Lab Hue Compatibility

Use CIE Lab

Legacy system interop. Hue agreement: CIE Lab 0 deg vs Helmlab 8.3 deg.

Transparency

Where We Lose

No color space wins everywhere. Here are our genuine weaknesses, documented publicly.

Where MetricSpace Loses

COMBVD sub-datasets
CIEDE2000 beats MetricSpace on LEEDS (19.25 vs 21.84), RIT-DuPont (19.47 vs 21.90), and WITT (30.22 vs 30.93). Our lead comes from the larger BFD-P datasets.
Mild overfitting
72 params on 3813 data points. Train/test gap of +1.8 STRESS. Published 22.48 is a training metric; cross-validated estimate is ~24.3. Still #1 among all competitors.
No HDR optimization
Jzazbz was designed for HDR/WCG. MetricSpace v21 is optimized for SDR psychophysical datasets. HDR color difference prediction is untested.
No surround adaptation
CAM16 models viewing conditions (dark/dim/light surround). MetricSpace has basic parameters but is not optimized for cross-surround.

Where GenSpace Loses 9 of 90 vs OKLab

sRGB Round-trip — NC LUT adds noise. Below visual threshold.
-34M x
Near-ach gradient CV — Real weakness. Grays less uniform.
-24%
Bright gradient CV — Marginal. Within noise.
-2%
Gradient CV p95 — Marginal. Tail-end outliers.
-2%
CVD deutan step — Real weakness. Green-blind see less distinction.
-30%
Primary hue disc sRGB — Hue jumps at sRGB primaries.
-26%
Primary hue disc P3 — Same issue in Display P3.
-27%
Red-to-White G-B — Effectively tied.
-2%
Ebner-Fairchild max — Slightly worse worst-case hue surface.
-6%
Quick Start

Works where you work

Python and JavaScript with identical APIs. TypeScript types included. Zero dependencies in JS.

from helmlab import Helmlab

hl = Helmlab()

# Generate a 10-shade palette from any color
palette = hl.palette("#3b82f6")

# Perceptual distance between two colors
dist = hl.delta_e("#ff0000", "#00ff00")

# 32-step gradient (smooth blue, not lavender)
grad = hl.gradient("#0000ff", "#ffffff", 32)

# Tailwind-style semantic scale (50-950)
scale = hl.semantic_scale("#3b82f6")
~2.5x
OKLab cost
us/px
per pixel
Exact
invertibility
0 deps
JS bundle (11.6KB)

Get Started

Python and JavaScript. Same API. Same results.

Python pip install helmlab
JS / TS npm install helmlab
MIT License Zero Dependencies (JS) TypeScript Included
FAQ

Frequently Asked Questions

What's the difference between GenSpace and MetricSpace?

GenSpace is optimized for visual quality in generation tasks: palette creation, gradient interpolation, gamut mapping, and animation. ~35 parameters, depressed cubic transfer. MetricSpace is optimized for predicting perceptual color differences. 72 parameters, full enrichment pipeline with H-K correction, pair-dependent SL/SC weighting. Same library, two pipelines.

Is Helmlab a replacement for OKLab?

For most generation tasks, yes. GenSpace scores 66-9 against OKLab across 90 benchmarks, including 6-1 on independent datasets OKLab was optimized on. OKLab remains better for: near-achromatic gradients (24% better CV), CVD deutan palettes (43%), native CSS oklch(), or minimal bundle size (~2KB vs 11.6KB).

How was it optimized? Is there overfitting?

CMA-ES optimization on COMBVD (3813 pairs). Proper holdout test: +1.8 STRESS gap between train and held-out 20% split. Published STRESS 22.48 is a training metric; cross-validated estimate ~24.3. Still beats all competitors (CIEDE2000: 29.20). MacAdam 1974 (never trained on) = 19.51, also #1. Full analysis in BENCHMARK.md.

Can I use it in CSS?

No native CSS support. Helmlab is a JS/Python library that outputs standard hex/RGB values. Use oklch() for CSS-native interpolation. Use Helmlab when generating colors in JS/Python code, design tokens, build-time palette generation, or server-side rendering.

What about browser support?

ES module, zero dependencies, 11.6KB gzipped. Works in all modern browsers and Node.js. TypeScript types included. Outputs standard hex/RGB. helmlab.js is tree-shakeable.

Is it open source?

MIT licensed. GitHub: github.com/Grkmyldz148/helmlab. Full benchmark methodology (ColorBench), optimization scripts, and psychophysical datasets are published. Research paper: arxiv.org/abs/2602.23010.