On one of pages we're currently working on users can change the background of the text displayed.
We would like to automatically alter the foreground colour to maintain reasonable contrast of the text.
We would also prefer the colour range to be discretionary. For example, if background is changing from white to black in 255 increments, we don't want to see 255 shades of foreground colour. In this scenario, perhaps 2 to 4, just to maintain reasonable contrast.
Any UI/design/colour specialists/painters out there to whip out the formula?
Contrast is calculated using "relative luminance", which is defined as: The relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white. The relative luminance can be calculated from any colour code (like HEX or RGB).
Finding a complementary color is very simple in the RGB model. For any given color, for example, red (#FF0000), you need to find the color, which, after being added to red, creates white (0xFFFFFF). Naturally, all you need to do, is subtract red from white and get cyan (0xFFFFFF - 0xFF0000 = 0x00FFFF).
Color contrast involves using two different colors with different amounts of tint and shade. Complementary colors are two colors that are opposite of each other on the color wheel. Orange and blue are two complementary colors that have synergy.
We can say that contrast is determined by the color and brightness of the object. Contrast is the difference between the maximum and minimum pixel intensity of an image. Formula: Contrast = maximum pixel intensity - minimum pixel intensity.
Basing your black-white decision off of luma works pretty well for me. Luma is a weighted sum of the R, G, and B values, adjusted for human perception of relative brightness, apparently common in video applications. The official definition of luma has changed over time, with different weightings; see here: http://en.wikipedia.org/wiki/Luma_(video). I got the best results using the Rec. 709 version, as in the code below. A black-white threshold of maybe 165 seems good.
function contrastingColor(color)
{
return (luma(color) >= 165) ? '000' : 'fff';
}
function luma(color) // color can be a hx string or an array of RGB values 0-255
{
var rgb = (typeof color === 'string') ? hexToRGBArray(color) : color;
return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]); // SMPTE C, Rec. 709 weightings
}
function hexToRGBArray(color)
{
if (color.length === 3)
color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2);
else if (color.length !== 6)
throw('Invalid hex color: ' + color);
var rgb = [];
for (var i = 0; i <= 2; i++)
rgb[i] = parseInt(color.substr(i * 2, 2), 16);
return rgb;
}
In terms of sheer readability, you want to use black and white text on whatever background it is. So convert RGB to HSV, and just check whether V is < 0.5. If so, white, if not, black.
Try that first and see if you find it attractive.
If you don't, then you probably want the white and black not to be so stark when your background is too bright or too dark. To tone this down, keep the same hue and saturation, and use these values for brightness:
background V foreground V
0.0-0.25 0.75
0.25-0.5 1.0
0.5-0.75 0.0
0.75-1.0 0.25
On a medium color, you'll still see black or white text which will be nicely readable. On a dark color or light color, you'll see the same color text but at least 3/4 away in terms of brightness and therefore still readable. I hope it looks nice :)
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