Detecting if an HTML colour is light or dark
Summary
The Farbtastic color picker in WordPress allows users to select colors, but it doesn't provide the corresponding text color. To automatically adjust text color based on the background color, you need to determine if the background color (such as #4933FF) is light or dark. This involves converting the hex color to RGB, then to HSL to assess lightness. The provided PHP functions facilitate this process, allowing you to call `light_or_dark()` to get the appropriate text color.
WordPress ships with the Farbtastic color picker, which is great if you want users to be able to select a colour. For a recent plugin I wanted users to be able to select a background colour of a div, but I also needed the text colour to work – that also needed to change automatically to suit the background colour.
Turns out Farbtastic does it, but doesn’t return the text colour in the return object.
So I need to check the HTML colour code, work out if it is light or dark and change the text colour to suit
So is #4933FF light or dark?
The human eye can do it easily, but working it out from the Hex RGB value is less intuitive.
First step is to convert it to decimal Red Green Blue values
function HTMLToRGB($htmlCode)
{
if($htmlCode[0] == '#')
$htmlCode = substr($htmlCode, 1);
if (strlen($htmlCode) == 3)
{
$htmlCode = $htmlCode[0] . $htmlCode[0] . $htmlCode[1] . $htmlCode[1] . $htmlCode[2] . $htmlCode[2];
}
$r = hexdec($htmlCode[0] . $htmlCode[1]);
$g = hexdec($htmlCode[2] . $htmlCode[3]);
$b = hexdec($htmlCode[4] . $htmlCode[5]);
return $b + ($g << 0x8) + ($r << 0x10);
}Then you need to work out Hue, Saturation and Lightness HSL
function RGBToHSL($RGB) {
$r = 0xFF & ($RGB >> 0x10);
$g = 0xFF & ($RGB >> 0x8);
$b = 0xFF & $RGB;
$r = ((float)$r) / 255.0;
$g = ((float)$g) / 255.0;
$b = ((float)$b) / 255.0;
$maxC = max($r, $g, $b);
$minC = min($r, $g, $b);
$l = ($maxC + $minC) / 2.0;
if($maxC == $minC)
{
$s = 0;
$h = 0;
}
else
{
if($l < .5)
{
$s = ($maxC - $minC) / ($maxC + $minC);
}
else
{
$s = ($maxC - $minC) / (2.0 - $maxC - $minC);
}
if($r == $maxC)
$h = ($g - $b) / ($maxC - $minC);
if($g == $maxC)
$h = 2.0 + ($b - $r) / ($maxC - $minC);
if($b == $maxC)
$h = 4.0 + ($r - $g) / ($maxC - $minC);
$h = $h / 6.0;
}
$h = (int)round(255.0 * $h);
$s = (int)round(255.0 * $s);
$l = (int)round(255.0 * $l);
return (object) Array('hue' => $h, 'saturation' => $s, 'lightness' => $l);
}Lastly you’ll need to detect whether it is light or dark
function light_or_dark($color){
$textColor = "#000000";
$rgb = HTMLToRGB($color);
$hsl = RGBToHSL($rgb);
if($hsl->lightness > 200) {
// this is light colour, so dark text
$textColor = "#000000";
}
else{
//this is dark color
$textColor = "#FFFFFF";
}
return $textColor;
}There you go! You will need all three functions but just call lightordark() with the HTML value e.g. #4933FF