How to check if hex color is "too black"?
Solution 1:
You have to extract the three RGB components individually, and then use a standard formula to convert the resulting RGB values into their perceived brightness.
Assuming a six character colour:
var c = c.substring(1); // strip #
var rgb = parseInt(c, 16); // convert rrggbb to decimal
var r = (rgb >> 16) & 0xff; // extract red
var g = (rgb >> 8) & 0xff; // extract green
var b = (rgb >> 0) & 0xff; // extract blue
var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709
if (luma < 40) {
// pick a different colour
}
EDIT
Since May 2014 tinycolor
now has a getBrightness()
function, albeit using the CCIR601 weighting factors instead of the ITU-R ones above.
EDIT
The resulting luma value range is 0..255, where 0 is the darkest and 255 is the lightest. Values greater than 128 are considered light by tinycolor
. (shamelessly copied from the comments by @pau.moreno and @Alnitak)
Solution 2:
I found this WooCommerce Wordpress PHP function (wc_hex_is_light) and I converted to JavaScript. Works fine!
function wc_hex_is_light(color) {
const hex = color.replace('#', '');
const c_r = parseInt(hex.substr(0, 2), 16);
const c_g = parseInt(hex.substr(2, 2), 16);
const c_b = parseInt(hex.substr(4, 2), 16);
const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
return brightness > 155;
}
Solution 3:
The TinyColor library (you've already mentioned it) provides several functions for inspecting and manipulating colors, among them:
-
getBrightness
Returns the perceived brightness of a color, from 0-255, as defined by Web Content Accessibility Guidelines (Version 1.0).
tinycolor("#fff").getBrightness(); // 255
-
isLight
Return a boolean indicating whether the color's perceived brightness is light.
tinycolor("#fff").isLight(); // true tinycolor("#000").isLight(); // false
-
isDark
Return a boolean indicating whether the color's perceived brightness is dark.
tinycolor("#fff").isDark(); // false tinycolor("#000").isDark(); // true
-
getLuminance
Returns the perceived luminance of a color, from 0-1 as defined by Web Content Accessibility Guidelines (Version 2.0).
tinycolor("#fff").getLuminance(); // 1
Solution 4:
You can compute the luminance:
Luminance is thus an indicator of how bright the surface will appear.
So it's great to choose if the text should be white or black.
var getRGB = function(b){
var a;
if(b&&b.constructor==Array&&b.length==3)return b;
if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])];
if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];
if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],
16)];
if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];
return (typeof (colors) != "undefined")?colors[jQuery.trim(b).toLowerCase()]:null
};
var luminance_get = function(color) {
var rgb = getRGB(color);
if (!rgb) return null;
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
}
The method above allows you to pass the color in different formats, but the algorithm is basically just in luminance_get
.
When I used it, I was setting the color to black if the luminance was greater than 180
, white otherwise.