# Color models

If someone knows only one color model, it's probably RGB. It's a great color space for computers to represent colors, but not intuitive or useful for humans. It's especially not useful when objectively determining whether a color is dark or light.

The screenshot above shows my Chrome extension Hue Tab. I had to use a luminance formula (different from RGB or HSL) to decide whether to use black or white text on the color sample.

## HSL (Hue-Saturation-Lightness)

HSL is a more intuitive color model than RGB because it describes colors by their Hue (red, yellow, green, blue, purple or anywhere in between), Saturation (color intensity), and Lightness (how bright a color is).

In HSL, lightness is calculated as the average of `max(r, g, b)` and `min(r, g, b)`.
In HSB, brightness is calculated as `max(r, g, b)`

The problem is that neither Lightness nor Brightness are a perfect representation of our sensitivity of luminance. Human eyes aren't as sensitive to colors in the purple or red regions as the greens and yellows. This is why blues seem darker than greens, even if they have the same mathematical L or B value.

# Luma coefficients

To approximate human perception of lightness, we need to use a weighted arithmetic mean. This table shows the percent at which each color is weighted at for the two most common luma coefficient standards.

Weighted MethodRGB
Rec. 601 (CCIR 601)29.9%58.7%11.4%
Rec. 70921.26%71.52%7.22%

Currently, the W3C recommends CCIR 601. Rec. 709 is much more commonly used in video editing.

## Rec. 601 luminance function

This JavaScript function finds the luminance of a hex color using Rec. 601 coefficients.

I made the cutoff for a color to be dark at < 55% luminance because personally, I think white on a light color looks better than black on a dark color.

``````// uses CCIR 601 luma coefficients
// input in #RRGGBB
function isDark(hex) {
// convert hexadecimal color into decimal
var decimal = parseInt(hex.substring(1), 16);

// extract red, green, and blue components separately
var r = (decimal >> 16) & 255;
var g = (decimal >> 8) & 255;
var b = decimal & 255;

// calculate CCIR 601 luma
var lightness = (0.299*r + 0.587*g + 0.114*b) / 255;
return (lightness < 0.55);
}
``````

# Demo

Here's a demo of the `isDark` function. Choose from the color picker, and it will tell you the luminance and change the text to either black or white to ensure maximum contrast.

Enable JavaScript for this demo to work.