Two pre-releases in the making, this release brings a lot of new color spaces, a new gamut mapping method, a smarter display(), a leaner dist/, and a pile of fixes.
If you have been following along with the v0.7.0-alpha.1 and v0.7.0-alpha.2 pre-releases, the only things new to you are in Changes since v0.7.0-alpha.2.
⬇️ Over 240 million downloads! 🤯
Color.js has now been downloaded over 240 million times on npm!
As a reminder, we have an Open Collective that you can fund directly.
If your company depends on Color.js in any way, it is in your best interest to ensure its future is sustainable.
🚨 Breaking changes
These are unlikely to break things for the majority of users, but theoretically could if you were doing weird stuff with Color.js 😜.
We cleaned up dist/ quite a bit with this release and re-evaluated what actually needs to be there:
- Removed the pre-built ESM bundles. We now only generate bundles for CJS and global builds. ESM exports point directly at the corresponding files in
src/. This also fixes a dual-instance bug where importing fromsrc/vs. the package root could yield differentColorregistries (by @LeaVerou in #739). - Removed the minified
.min.*files from the package, since packages are moving away from providing these and minification is becoming a consumer concern (by @LeaVerou in #741).
For those of you that have been importing files directly from colorjs.io, removed files now redirect to the versions still there (e.g. colorjs.io/dist/color.min.js and colorjs.io/dist/color.js now both redirect to colorjs.io/src/color.js), so your code should continue to work.
New color spaces
- 🆕 Gamut-relative (OK)LCH spaces (by @LeaVerou in #736) Ever tried to use (OK)LCH and kept struggling with the irregularity of the gamut shape? You can now have your cake and eat it too, as we introduced gamut-relative versions of these spaces, where
c = 1is the most colorful in-gamut color at a given lightness and hue so you never have to worry about getting out of gamut! These new spaces are:oklch-p3,oklch-srgb,oklch-rec2020,lch-p3,lch-srgb,lch-rec2020.- All six are built on a new general
GamutRelativeColorSpaceclass that can be easily used to generate such color spaces for any gamut and color space, as long as there is a coordinate to reduce that is guaranteed to get you in-gamut. - Note that this loses you some of the perceptual uniformity of the original spaces, but it is a tradeoff that is often worth it for the convenience of staying in-gamut. After all, perceptual uniformity only applies in-gamut anyway.
- 🆕
hsl-p3andhsl-rec2020: HSL syntax, wider gamut (by @LeaVerou in #735) - 🆕 The experimental Helmlab family of perceptual color spaces:
helmlab-metric(Helmlab MetricSpace),helmgen(HelmGen), andhelmgenlch(HelmGenLCh) (by @Grkmyldz148)
Other new features
- 🆕 Smarter
display()fallback When a color isn't natively supported by the browser,display()now stays as close as possible to the original color: it walks up the base color space chain (closest first) and uses the first supported ancestor, preserving the color's gamut (e.g. anhsl-p3color falls back tocolor(display-p3 …)rather thanlab()) instead of always jumping to the widest default. Adds an opt-indisplaySpacesoverride onColorSpace, a parameterizablesupports(), and aDisplayOptionsinterface (by @LeaVerou in #738) - 🆕 New gamut mapping method:
raytrace. It traces a ray to the gamut boundary instead of binary-searching, automatically determining the RGB gamut and linear space from the space object (by @facelessuser) - 🆕 New deltaE method:
deltaEHelmlab, based on the Helmlab model (by @Grkmyldz148) - 🆕 Added a
collapseoption toserialize()/Color.toString()to disable collapsing for hex colors (e.g. keep#ff0066instead of collapsing it to#f06) (by @MysteryBlokHed in #712)
For plugin/library/tooling authors
Exposed more internals, so you never have to duplicate stuff that Color.js already knows about:
- Expose transformation matrices via
ColorSpace.MColor spaces now expose the transformation matrices they use internally through a newMproperty, so consumers can reuse them instead of duplicating the data. Matrices for RGB spaces can also be supplied via the genericMoption (by @LeaVerou in #749) - Matrix algebra utilities Added
inv(matrix inversion) andsolveto the math utilities, so external libraries are no longer required when developing new color spaces (by @facelessuser) - Polar spaces declare their hue coordinate via the new
ColorSpace#hueIdandColorSpace#hueIndex, so code that needs the hue angle can look it up from the space definition instead of assuming it is namedh(by @svgeesus in #754)
Changes since v0.7.0-alpha.2
Bug fixes
- Premultiplied interpolation is now correct in polar spaces (by @svgeesus in #754). Premultiplication used to multiply every coordinate by alpha, including the hue angle, which is meaningless. Per CSS Color 4 § 13.3, the hue angle is never premultiplied, and un-premultiplication must not divide by a zero or
nonealpha. Concretely:- The hue angle is skipped when premultiplying and when undoing it, and is found from the space definition, so spaces whose hue coordinate isn't called
h(e.g.hzin Jzczhz) now interpolate correctly too. - Un-premultiplying by an alpha of
0leaves the coordinates untouched instead of dividing by zero and producingNaN. - A
nonealpha is carried forward from the other color before premultiplying, per CSS Color 4 § 13.2, and staysnoneonly if both colors are missing it. Previously anonealpha premultiplied every coordinate to zero, turning the color black.
- The hue angle is skipped when premultiplying and when undoing it, and is found from the space definition, so spaces whose hue coordinate isn't called
helmgenlchnow serializes ascolor(--helmgenlch …)instead of the invalidcolor(helmgenlch …), by giving it thecssIdits sibling spaces already had (by @Grkmyldz148, fixes #730)- Gamut surface threshold updated, and the values for 32 bit vs 64 bit are now documented:
1e-12gives better resolution for 64 bit values, while1e-6is the right choice for 32 bit (by @facelessuser in #752)
For contributors
- Added an AI-assisted contributions section to CONTRIBUTING.md, spelling out our expectations for PRs written with AI assistance (by @Grkmyldz148, closes #723)
Other bug fixes & performance
These landed in the pre-releases:
- Preserve a subclass's own
toBase/fromBasewhen options omit them, instead of clobbering prototype methods withundefined(by @LeaVerou) - Add the
typesfield back topackage.json(by @MysteryBlokHed in #714) - Avoid implied color space dependencies for procedural usage, so consumers no longer need to manage them manually (by @aduth in #734)
- Reduce a CAM16 calculation in the worst-case scenario (by @facelessuser)
- Fix HCT tests and related calculations (by @facelessuser)
- Fix the CI install command after the lockfile removal (by @MysteryBlokHed in #744)
Full Changelog: v0.6.1...v0.7.0
New Contributors
- @Grkmyldz148 made their first contribution (Helmlab color spaces and
deltaEHelmlab) - @aduth made their first contribution in #734