# Black or white text on a colour background?

By

How to calculate programmatically whether black text or white text is more readable on a colour background?

Here are some algorithms to calculate the brightness of a color. The example code is written in PHP, but you should be able to adapt the code examples to any other programming language. All of the algorithmns are applied on the following color map to have a first impression how they perform.

## Arithmetic Mean

f'(x)= \frac{a+b+c}{3}

In Code, this looks like:

PHP
function arithmeticMean($hex) {$rgb = ColorUtils::hex2rgb($hex); return ($rgb[0] + $rgb[1] +$rgb[2]) / 3;
}

This results in an output for black/white text like:

This is a very simple and effective algorithm. Unfortunately it fails between the green and turquoise region:

The quick brown fox jumps over the lazy dog

## Geometric Mean

f'(x)=\sqrt[n]{rgb}

In Code, this looks like:

PHP
function geometricMean($hex) { var$rgb = ColorUtils::hex2rgb($hex); return pow($rgb[0] * $rgb[1] *$rgb[2], 1/3);
}

This results in an output for black/white text like:

Now the text is much better with the green background, but now the brightness of the yellow is wrong:

The quick brown fox jumps over the lazy dog

f'(x)= \sqrt{\frac{r^2 +g^2+ b^2}{3}}

In Code, this looks like:

PHP
function quadraticMean($hex) { var$rgb = ColorUtils::hex2rgb($hex); return sqrt( (pow($rgb[0], 2) + pow($rgb[1], 2) + pow($rgb[2], 2)) / 3);
}

This results in an output for black/white text on a colour background:

Works really well for all dark colours. Fails on purple.

The quick brown fox jumps over the lazy dog

## HSV Value (Brightest Component)

f'(x)= max(r,g,b)

In Code, this looks like:

PHP
function valueFromHSV($hex) { var$hsv = ColorUtils::hex2hsv($hex); return$hsv[2] * 255;
}

This results in an output for black/white text like:

Dark colours are ok, Fails when the r, g or b value is close to 0x99.

## Darkest Component

f'(x)= min(r,g,b)

In Code, this looks like:

PHP
function valueFromHSV($hex) { var$rgb = ColorUtils::hex2rgb($hex); return min($rgb[0], $rgb[1],$rgb[2]);
}

This results in an output for black/white text like:

Only the very bright colours work fine with this algorithm.

The quick brown fox jumps over the lazy dog

## 3D distance in RGB space

f'(x)= \sqrt{r^2 +g^2+ b^2}

In Code, this looks like:

PHP
function distanceIn3D($hex) { var$rgb = ColorUtils::hex2rgb($hex); return sqrt( pow($rgb[0], 2) + pow($rgb[1], 2) + pow($rgb[2], 2));
}

This results in an output for black/white text like:

Worse than using the V component of the HSV representation.

The quick brown fox jumps over the lazy dog

## Lightness From HSL

In Code, this looks like:

PHP
function lightnessFromHSL($hex) { var$hsl = ColorUtils::hex2hsl($hex); return$hsl[2] * 255;
}

This results in an output for black/white text on a colour background:

The best unweighted formula. Fails on yellow around 0xeeee00.

The quick brown fox jumps over the lazy dog

## Weighted W3C Formula

Natural formulas don’t take into consideration that the human eye perceives some of the primary colours darker than others.

Eg pure green(0xff0000) is perceived brighter than pure blue(0x00ff00).
According to the W3C consortium, this biased perception can be modelled with the following weights:

r *= .299
g *= .587
b *= .111
f'(x)= r\cdot0.299 +g\cdot0.587+ b\cdot0.111

In Code, this looks like:

PHP
function weightedW3C($hex) { var$rgb = ColorUtils::hex2rgb($hex); return$rgb[0] * 0.299 + $rgb[1] * 0.587 +$rgb[2] * 0.114;
}

This results in an output for black/white text like:

Very good algorithm, works really well.
Source: https://www.w3.org/TR/AERT/#color-contrast

The quick brown fox jumps over the lazy dog

## Weighted Distance in 3D RGB Space

f'(x)= \sqrt{r^2\cdot0.241 +g^2\cdot0.691+ b^2\cdot0.068}

In Code, this looks like:

PHP
function weightedDistanceIn3D($hex) { var$rgb = ColorUtils::hex2rgb($hex); return sqrt(pow($rgb[0], 2) * 0.241 + pow($rgb[1], 2) * 0.691 + pow($rgb[2], 2) * 0.068);
}

This results in an output for black/white text on a colour background:

This is an improved version of the W3C fomula.
Source: https://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx

The quick brown fox jumps over the lazy dog

## ColorUtils

The used ColorUtils class above consists of methods that are used to convert colors between different color spaces. The library is available here.

If you are interested in the source code to generate the color map examples above:

Photo by Markus Spiske on Unsplash. Image map by Wikimedia Commons.