I'm trying to find a method for determining whether to use black or white text, given a background color (as a hex value). Has anyone dealt with this before? Is there an effective way to do this?
In my case, I would be using PHP to implement the logic (though any experience with this in other languages is welcome).
Contrast with a White Background. Black text on a white background provides maximal value contrast and, therefore, optimal readability for body text. Black text on a white background provides maximal value contrast and, therefore, optimal readability for body text.
Black backgrounds: High-chroma colors are best for black backgrounds because they offer a good contrast ratio without the eye fatigue (which occurs with white text on a black background).
Optimal legibility requires black text on white background (so-called positive text). White text on a black background (negative text) is almost as good. Although the contrast ratio is the same as for positive text, the inverted color scheme throws people off a little and slows their reading slightly.
Yellow can work on a black background, but it's as much about fonts and where the colour is used that affect the overall look of the site. Make sure you're using fonts that are easily legible and you only use yellow for highlighting, as you have done.
Take a look at this page: Calculating Color Contrast with PHP
Keep in mind that if black and white are your only choices you're bound to have cases where neither of them works particularly great.
I think the best way is the Luminosity Contrast
algorithm:
function getContrastColor($hexColor) { // hexColor RGB $R1 = hexdec(substr($hexColor, 1, 2)); $G1 = hexdec(substr($hexColor, 3, 2)); $B1 = hexdec(substr($hexColor, 5, 2)); // Black RGB $blackColor = "#000000"; $R2BlackColor = hexdec(substr($blackColor, 1, 2)); $G2BlackColor = hexdec(substr($blackColor, 3, 2)); $B2BlackColor = hexdec(substr($blackColor, 5, 2)); // Calc contrast ratio $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($R2BlackColor / 255, 2.2) + 0.7152 * pow($G2BlackColor / 255, 2.2) + 0.0722 * pow($B2BlackColor / 255, 2.2); $contrastRatio = 0; if ($L1 > $L2) { $contrastRatio = (int)(($L1 + 0.05) / ($L2 + 0.05)); } else { $contrastRatio = (int)(($L2 + 0.05) / ($L1 + 0.05)); } // If contrast is more than 5, return black color if ($contrastRatio > 5) { return '#000000'; } else { // if not, return white color. return '#FFFFFF'; } } // Will return '#FFFFFF' echo getContrastColor('#FF0000');
Some results:
NOTE: The font color is determined by the previous function. The number in brackets is the contrast ratio.
Another simpliest and less precise way called YIQ
(because it converts the RGB color space into YIQ):
public function getContrastColor($hexcolor) { $r = hexdec(substr($hexcolor, 1, 2)); $g = hexdec(substr($hexcolor, 3, 2)); $b = hexdec(substr($hexcolor, 5, 2)); $yiq = (($r * 299) + ($g * 587) + ($b * 114)) / 1000; return ($yiq >= 128) ? 'black' : 'white'; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With