better-color-tools
Color parser and better color manipulation through the power of science! 🧪 Uses Oklab/Oklch for better color operations.
The JS version of this libray is fast (~200k
ops/s), lightweight (5 kB
gzip), and dependency-free. The Sass version… is Sass (which has no runtime).
👉 Playground: https://better-color-tools.pages.dev/
Usage
npm install better-color-tools
JavaScript
Works in the browser (ESM) and Node (14+).
Importing
import better from 'better-color-tools';
Parse
better.from('#b3f6e6');
better.from(0xb3f6e6);
better.from('rebeccapurple');
better.from('rgb(136, 48, 62)');
better.from('hsl(210, 85%, 37%)');
better.from('oklab(48.56949% -0.03971 -0.14459)');
better.from('oklch(83.11253% 0.22612 147.35276)');
This library understands any CSS-valid color, including CSS Color Module 4 (but if some aspect isn’t implemented yet, please request it!).
Convert
This library converts to most web-compatible formats¹, with an emphasis on usefulness over completeness:
- sRGB (hex):
better.from('…').hex
/ better.from('…').hexVal
- sRGB (RGB):
better.from('…').rgb
/ better.from('–').rgbVal
- Oklab:
better.from('…').oklab
/ better.from('…').oklabVal
- Oklch:
better.from('…').oklch
/ better.from('…').oklchVal
- XYZ:
better.from('…').xyz
/ better.from('…').xyzVal
¹The following formats aren’t supported as outputs:
- HSL isn’t supported because you shouldn’t use it
- HWB isn’t supported because it’s another form of HSL
- HSV is a great colorspace, but on no standards track for the web currently
- CIE L*a*/CIE L*C*h aren’t supported because Oklab/Oklch are superior
For a comprehensive color conversion library, see culori.
Mix
better.mix('red', 'lime', 0.35);
better.mix('blue', 'magenta', 0.5, 'srgb-linear');
This uses Oklab (best) by default, but also supports oklch
, lms
, sRGB
, and linearRGB
colorspaces for mixing.
Lighten / Darken
better.lighten('red', 0.5);
better.darken('red', 0.5);
This takes hue and human perception into account for visually-accurate results. Also, fun fact: both functions accept negative values.
Lightness
Get the human-perceived lightness of any color (identical to the first value of .oklabVal
)
better.lightness('#fc7030');
Manipulation
import better, { colorFn } from 'better-color-tools';
let [L, C, h] = better.from('#5a00a6').oklchVal;
h += 5;
C += 0.01;
better.from(colorFn('oklch', [L, C, h])).hex;
Manipulation is best done in a space like Oklch which is optimized for manual tweaking.
Sass
Works with any version of Dart Sass (the current version).
Importing
@use 'better-color-tools' as better;
Mix
.foo {
color: better.mix('red', 'lime', 0.35);
}
Uses Oklab for best results (which yields much better results than Sass’ mix).
Lighten / Darken
.foo:hover {
color: better.lighten('blue', 0.2);
border-color: better.darken('blue', 0.15);
}
Lightens (or darkens) color via Oklab for human-perceived lightness value (which yields much better results than Sass’ lighten/darken:
P3
.foo {
color: better.p3(#f00);
}
Convert any Sass-readable color to P3.
Fallback
.foo {
@include better.fallback('color', better.p3(#f00), #f00);
}
Mixin for adding CSS fallbacks. Can take infinite arguments. Specify desired format first, followed by fallbacks.
Oklab
$oklab: better.rgbToOklab(#f00);
$rgb: better.oklabToRGB($oklab);
Converts any Sass-readable color to an Oklab map of (l: …, a: …, b: –)
. The Sass map can either be used to make a CSS string:
@use 'sass:map';
.foo {
color: oklab(#{map.get($oklab, 'l')} #{map.get($oklab, 'a')} #{map.get($oklab, 'b')});
color: better.oklabToRGB($oklab);
}
Or for color manipulation:
$oklab-lighter: map.set($oklab, 'l', 0.8);
Lightness
Get the human-perceived lightness of any color (identical to the first value of .oklabVal
):
$lightness: better.lightness(#f00);
Project summary
This project is meant to provide the best possible method for common color operations such as mixing, lightening/darkening, and conversion. This library is not comprehensive, and doesn’t support any colorspaces that don’t serve a practical purpose
(limiting colorspaces helps this library optimize for performance over completeness, not to mention ease-of-use). If you are well-versed in color science and need a comprehensive library, consider Culori or Color.js instead.
To learn more, see Project Goals