Calculating Color Contrast with PHP
An essential step in web design is choosing the right colors. Not only should they “look good”, but they should also be easy on the eye. This is especially important if you want your visitor to read longer texts.
A good designer will choose high contrast colors for backgrounds and texts without hesitation. But sometimes no human is involved in choosing the colors. For example when colors are assigned in a (pseudo) random manner.
After some googling I found a page explaining different color contrast algorithms. I used the data from that page and implemented 3 color check functions in PHP.
Some short description and the source code for the functions is below. The impatient can just try it at my test page:
All 3 functions expect the RGB values (0-255) of 2 colors and will return a number. The higher the number, the better the contrast is. Depending on your use case you can then set up a threshold you do not want to drop below.
Color Difference
This is a very simple algorithm that works by summing up the differences between the three color components red, green and blue. A value higher than 500 is recommended for good readability.
function coldiff($R1,$G1,$B1,$R2,$G2,$B2){ return max($R1,$R2) - min($R1,$R2) + max($G1,$G2) - min($G1,$G2) + max($B1,$B2) - min($B1,$B2); }
Brightness Difference
This function is a bit more advanced as it tries to compare the brightness of the colors. A return value of more than 125 is recommended. Combining it with the color difference above might make sense.
function brghtdiff($R1,$G1,$B1,$R2,$G2,$B2){ $BR1 = (299 * $R1 + 587 * $G1 + 114 * $B1) / 1000; $BR2 = (299 * $R2 + 587 * $G2 + 114 * $B2) / 1000; return abs($BR1-$BR2); }
Luminosity Contrast
The third function is most complex but seems to work best. It uses the luminosity to calculate the difference between the given colors. The returned value should be bigger than 5 for best readability.
function lumdiff($R1,$G1,$B1,$R2,$G2,$B2){ $L1 = 0.2126 * pow($R1/255, 2.2) + 0.7152 * pow($G1/255, 2.2) + 0.0722 * pow($B1/255, 2.2); $L2 = 0.2126 * pow($R2/255, 2.2) + 0.7152 * pow($G2/255, 2.2) + 0.0722 * pow($B2/255, 2.2); if($L1 > $L2){ return ($L1+0.05) / ($L2+0.05); }else{ return ($L2+0.05) / ($L1+0.05); } }
Update: Pythagorean Distance
Manni suggested to use the Pythagorean Distance in the comments. I ported his code to PHP. However I found it hard to find a good threshold. Sometimes well contrasting colors return a very low value, sometimes their value is very high. I settled for a threshold of 250 in my script, but suggest to use the luminosity contrast function above instead.
function pythdiff($R1,$G1,$B1,$R2,$G2,$B2){ $RD = $R1 - $R2; $GD = $G1 - $G2; $BD = $B1 - $B2; return sqrt( $RD * $RD + $GD * $GD + $BD * $BD ) ; }