Color.js Released

Published on

Related: Lea's blog post for the release of color.js

It has taken Lea and I far too long – there is always something more that really should be added, always some conversion that really needs an authoritive set of data to validate our code against – but we finally decided, time to actually release Color.js.

By which, I guess, we mean removing the polite figleaf that said, “whoops you stumbled on an unreleased thing, please be careful and lower your expectations”.

Because people are already using it to make demos and to check other color conversion code against (this includes some browser implementations of CSS Color 4 and CSS Color 5).

Lots of color spaces

Color.js is a JavaScript library – which you can use on a web page, or from node, or run locally – to make, modify, and manipulate colors in a wide variety of color spaces.

That includes all the predefined color spaces from CSS Color 4, plus the Device-independent Colors: CIE Lab and LCH, OKLab and OKLCH plus of course all the legacy color syntaxes.

In addition it includes some spaces useful for HDR, like rec2100-pq and rec2100-hlg, Jzazbz, ICTCP and a couple of color spaces from the film and tv industry (ACESScc for color grading, ACEScg for physical rendering and compositing).

Speaking personally, being able to create examples in all those color spaces, and accurately convert them to other color spaces, was essential to me for making examples, creating diagrams, writing and verifying browser tests, and for sanity checking the CSS Color 4 specification in the days before browsers started implementing it.

Why do we need it

Now, CSS Color 4 includes simple (but accurate) Sample code for Color Conversions so what extra does color.js add?

Well, the sample code is purely procedural, lots of easy-to-understand but tiny, single-purpose functions, so to use it you really need to apply a bunch of operations, one after another, not missing any out. All done using simple arrays, so remember to keep track of what each one contains!

To take an example: convert color(prophoto-rgb 0.7 0.2 0.65) to oklch. Using the sample code:

let mycolor = [0.7, 0.2, 0.65]; // this is ProPhoto by the way
let myoklch = OKLab_to_OKLCH(XYZ_to_OKLab(D65_to_D50(
lin_ProPhoto_to_XYZ(lin_ProPhoto(mycolor)))));

(Prophoto uses the D50 whitepoint while OKLCH uses D65, so there is a chromatic adaptation step in the middle there)

Now let's do that in color.js:

let mycolor = new Color('color(prophoto-rgb 0.7 0.2 0.65)');
let myoklch = mycolor.to('oklch');

Each color object contains, not just the actual color coordinates, (and the alpha, if it is not fully opaque) but also an explicit color space identifier. The code can look up what white point each color space uses, and can figure out how to convert between any pair of them.

Notice that the color can be specified exactly the same way you would in CSS, and that conversion is as simple as saying where you want to go. (Internally, the exact same set of steps as the first example are carried out, for you).

Here is a handy color conversion app, written in color.js, which I use all the time.

Interpolating colors

On the legacy web, you can make a gradient between two (or more) colors. As long as all are in sRGB, missing out around a third of all the colors most modern screens can display. And provided the interpolation is carried out in sRGB too, giving muddy, too-dark mixtures and tempting you to add just a couple more gradient stops to get things looking right.

CSS Color 4 explains how to interpolate any two colors regardless what color space they were originally in. And you get to pick the color space used for interpolation, too: diffeent ones give very different results. For example:

linear-gradient(in lab to right, white, #01E)
linear-gradient(in srgb to right, white, #01E)
linear-gradient(in oklab to right, white, #01E)

The middle gradient of these three, in sRGB, is too dark and a bit purplish. The top one, in CIE Lab, is way too purple while the bottom one in shiny new OKLab has a nicely even lightness throughout and no purple shift at all.

This rendering of the brand-new CSS Images 4 gradient syntax was generated in color.js, using the gradient interpolation demo app

Gradients aren't the only time colors are interpolated on the web; just one of the prettiest to show. Animations, transitions, compositing and CSS Color 5 color-mix() also use interpolation, and color.js has you covered until all the browsers implement all of this (and beyond, because older browsers will always need a helping hand).

And that's not all

I haven't even talked about automatic gamut mapping, which brings undisplayable colors into gamut while trying to keep them as similar-looking as possible. Or the several different color difference (ΔE) formulae that color.js supports. Or the alternate Chromatic Adaptation Transform methods you can use. Or just little utility functions to get luminance (on any color) or the u,v chromaticity coordinates, for making diagrams.

But this is a release announcement not a tutorial, so I had best be ending here.

Get color.js, enjoy, and report bugs!!