Output

Eventually, no matter what your calculations are, you will want to display some kind of output, most likely on a web page, frequently in CSS. This page is all about that.

Getting a string representation of a color

color.toString() is a swiss army knife for many of your serialization needs. In fact, you may have used it without knowing, since Javascript calls it implicitly with no params when you coerce an object to a string:

let magenta = new Color("srgb", [1, 0, .4]);
"I love " + magenta;

While this may suffice for some uses, in many cases you will want to provide parameters to customize the result. Here are a few examples.

Disable gamut mapping

let funkyMagenta = new Color("p3", [1, 0, .4]);
funkyMagenta = funkyMagenta.to("srgb");
funkyMagenta.toString(); // gamut mapping by default
funkyMagenta.toString({inGamut: false}); // disable gamut mapping

Note that you cannot disable gamut mapping in `certain color spaces whose conversion math doesn't make sense for out of gamut values. These are typically the polar forms of gamma-corrected sRGB (HSL, HWB, HSV etc).

Change precision

By default, values are rounded to 5 significant digits. You can change that with the precision parameter:

let pink = new Color("lch", [70, 50, 350]);
pink = pink.to("srgb");
pink.toString();
pink.toString({precision: 1});
pink.toString({precision: 2});
pink.toString({precision: 3});
pink.toString({precision: 21});

Building an app that needs high precision? You can change the default precision of 5 globally by setting Color.defaults.precision!

Get a CSS color value that is actually supported by the current browser

When using sRGB or HSL, you can just use the output of color.toString() directly in CSS. However, with many color spaces, and most browsers, this is not the case yet.

One way to go about with this is to check if the value is supported and convert it if not:

let green = new Color("lch", [80, 80, 120]);
let cssColor = green.toString();
if (!CSS.supports("color", cssColor))
    cssColor = green.to("srgb").toString();

This works fairly well, but the browser may support a wider gamut than sRGB, and it forces everything into sRGB. An iterative approach may be better:

let green = new Color("lch", [80, 80, 120]);
let cssColor = green.toString();
if (!CSS.supports("color", cssColor))
    cssColor = green.to("p3").toString();
if (!CSS.supports("color", cssColor))
    cssColor = green.to("srgb").toString();
cssColor;

As of June 2020, cssColor will be sRGB in Chrome and Firefox, and P3 in Safari, providing access to 50% more colors than sRGB!

So, this works, but the process is a little tedious. Thankfully, Color.js has got your back! Simply use the fallback parameter. If set to true it will use the default set of fallbacks (P3, then sRGB), but you can also provide your own. Let's rewrite the example above using the fallback parameter!

let green = new Color("lch", [80, 80, 120]);
let cssColor = green.toString({fallback: true});
let cssColor2 = green.toString({fallback: ["p3", "hsl"]});

You can change the default set of fallbacks by setting Color.defaults.fallbackSpaces.

What if you want access to the converted color? For example, you may want to indicate whether it was in gamut or not. You can access the color property on the returned value:

let green = new Color("lch", [80, 90, 120]);
let cssColor = green.toString({fallback: true});
cssColor.color.inGamut();

While color.toString() returns a primitive string in most cases, when fallback is used it returns a String object so that it can have a property (primitives in Javascript cannot have properties).

Creating a CSS gradient from a range

When working with ranges, you may often need to display the range as a CSS gradient. The trick here is to grab as many steps as you need via color.steps(), then use them as gradient color stops. If you don't know how many steps you need, this is what the maxDeltaE parameter is for, as it lets you specify the maximum allowed deltaE between consecutive colors.

let r = Color.range("hsl(330 90% 50%)", "hotpink");
let stops = Color.steps(r, {steps: 5, maxDeltaE: 3});
let element = document.querySelector("#test");
element.style.background = `linear-gradient(to right, ${
    stops.join(", ")
})`;

Play with the parameters above to see what gradient is produced, or use the gradients demo app!

Note that in the example above, color.toString() is called implicitly with no params due to array.join(). You can also map the colors to strings yourself:

let r = Color.range("rebeccapurple", "gold");
let stops = Color.steps(r, {steps: 10});
let element = document.querySelector("#test2");
element.style.background = `linear-gradient(to right, ${
    stops.map(c => c.toString({precision: 2})).join(", ")
})`;