HUSL is a human-friendly alternative to HSL.
CIELUV, a color space designed for perceptual uniformity based on human experiments. When accessed by polar coordinates, it becomes functionally similar to HSL with a single problem: its chroma component doesn't fit into a specific range.
you can seeHUSL extends CIELUV with a new saturation component that allows you to span all the available chroma as a neat percentage.
H | |||
---|---|---|---|
S | |||
L |
HUSL is implemented as a set of functions to convert colors between RGB, HUSL and HUSLp. Check the individual ports for documentation and licensing. Most of the code is released under the MIT license. The math is available under the public domain.
The reference implementation is in JavaScript. This code is used to generate a snapshot of the color space. These snapshots, serialized in JSON, are used for regression testing. If you want to port HUSL to a different language or finish one of the started ports, you should match your implementation against the snapshot generated by the reference implementation. The snapshots are . Contact the original author by .
HSL | CIE LChuv | HUSL | HUSLp | |
---|---|---|---|---|
Lightness | Relative | Absolute | Absolute | Absolute |
Saturation* | Relative | Absolute | Relative | Absolute |
Hue uniformity | Poor | Good | Good | Good |
Component ranges | Defined | Undefined | Defined | Defined |
Saturated colors | Yes | Yes | Yes | No |
* Saturation and chroma are actually distinct concepts |
The dips in the graph represent impossible colors (such as dark saturated yellow). CIE LChuv doesn't warn you about them, making it unsuitable for generating colors.
HUSL preserves the lightness and hue components of CIE LChuv and stretches its chroma so that every color has the same range, defined as a percentage.
HUSLp takes as many colors as it can from CIE LChuv without distorting the chroma. As you can see, the resulting color space is smooth, but only pastel colors can be included.
The chroma component of CIE LChuv is absolute. Unlike HSL's saturation you can effectively use it to compare two different colors.
Both HSL and HUSL have a distorted chroma map, this is a trade-off of their convenient shape. Admittedly, HUSL's chroma has more sudden shifts.
This is why HSL is useless for working out contrast. The actual lightness varies drastically between hues.
For this demo I am using CIE's definition of lightness. Both CIE LChuv and HUSL use this component, so their picture is an even gray.
Let's try to generate some random background colors:
function randomHue() {
return Math.floor(Math.random() * 360);
}
$(...).css('background-color', $.husl.toHex(randomHue(), 90, 60));
$(...).css('background-color', hslToHex(randomHue(), 90, 60));
HUSL's uniform hue means random colors will be truly random. Iterating over colors will also produce better results.
$('#rainbow-husl div').each(function(index) {
$(this).css('background-color', $.husl.toHex(index * 36, 90, 60));
});
$('#rainbow-hsl div').each(function(index) {
$(this).css('background-color', hslToHex(index * 36, 90, 60));
});
HUSL is defined as a conversion to and from CIE LChuv. For both HUSL and HUSLp, the first step is to find the chroma bounds for a given lightness. These are lines, crossing which will push the color out of the RGB gamut. We define a function, getBounds(L) which returns 6 straight lines in slope-intercept format. Each of them represents one of three RGB channels being pushed either below 0 or above 1.
HUSL:
HUSLp:
I used Maxima to build and solve these equations, and is bundled with the code explaining how to get the bounding lines. The rest is simple geometry you can see in the reference implementation.