Given a background color, black or white text?

20,763

Solution 1

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.

Solution 2

Luminosity Contrast algorithm

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:

enter image description here

NOTE: The font color is determined by the previous function. The number in brackets is the contrast ratio.



YIQ algorithm (less precise)

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';
}                   

Solution 3

  function getTextColour($hex){
    list($red, $green, $blue) = sscanf($hex, "#%02x%02x%02x");
    $luma = ($red + $green + $blue)/3;

    if ($luma < 128){
      $textcolour = "white";
    }else{
      $textcolour = "black";
    }
    return $textcolour;
  }

Solution 4

Here is an algorithm that can be used to calculate a luminosity contrast ratio of your text:

http://juicystudio.com/services/aertcolourcontrast.php

You could use this formula with white and black values to calculate which gives you the higher ratio, and thus more readable text.

Solution 5

You should take a look at the CSS Color library. It's implemented in PHP and does all the hard work for you.

Share:
20,763
Wilco
Author by

Wilco

Updated on July 09, 2022

Comments

  • Wilco
    Wilco almost 2 years

    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).

  • Warren Young
    Warren Young over 14 years
    +1 Calculating the luminance or brightness of the color is far superior to averaging the RGB values. #FF0000 is bright red, not a dark color that the average of 85 would lead you to believe. In the HSB system (0-100% scale for B), you get B=100 for bright red. In the Lab system, you only get 54, probably more useful, since it's above the 50% point, indicating that you should use black against it, not white.
  • ashleedawg
    ashleedawg over 4 years
    Here's a compressed version, if you can supply the R/G/B values (out of 255) : function textColor($r,$g,$b) { return ((0.2126*$r/255)+(0.7152*$g/255)+(0.0722*$b/255)>=0.5?'#000'‌​:'#FFF'); }
  • Benbb96
    Benbb96 over 4 years
    I've adapted the first function to Python if anyone is looking for it : gist.github.com/Benbb96/e7b1ce654f616da08e61fa888e666354
  • tomloprod
    tomloprod over 4 years
    @Benbb96 Good job
  • andrewmacpherson
    andrewmacpherson about 2 years
    Beware: the formula in the splitbrain.org article is from an early <a href="w3.org/TR/2006/WD-WCAG20-TECHS-20060427/#G18">working draft of WCAG 2.0 techniques</a>. The formula and required ratio changed in the final version.
  • andrewmacpherson
    andrewmacpherson about 2 years
    Beware: the luminosity contrast algorithm used here is based on an early working draft of WCAG 2.0 techniques. The formula and required ratio changed in the final version.