How to check if hex color is "too black"?

Viewed 64925

I'm trying to evaluate the darkness of a color chosen by a color picker to see if it's "too black", and if so, set it to white. I thought I could use the first characters of the hex value to pull this off. It's working, but it's switching some legitimately "light" colors too.

I have the following code:

if (lightcolor.substring(0, 3) == "#00" || lightcolor.substring(0, 3) == "#010") {
  lightcolor = "#FFFFFF";
  color = lightcolor;
}

There must be a more efficient way with hex math to know that a color has gone beyond a certain level of darkness? Like if lightcolor + "some hex value" <= "some hex value" then set it to white.

I have tinyColor added, which might be of use for this, but I don't know for sure.

9 Answers

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

@Sliffcak, thanks for comment... To use substring, because substr was deprecated:

function wc_hex_is_light(color) {
    const hex = color.replace('#', '');
    const c_r = parseInt(hex.substring(0, 0 + 2), 16);
    const c_g = parseInt(hex.substring(2, 2 + 2), 16);
    const c_b = parseInt(hex.substring(4, 4 + 2), 16);
    const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
    return brightness > 155;
}

I combined the answers of @Alnitak and @SergioCabral below. I also implemented a hex value parser that works for standard and short forms.

const hexToRgb = (hex) =>
  (value =>
    value.length === 3
      ? value.split('').map(c => parseInt(c.repeat(2), 16))
      : value.match(/.{1,2}/g).map(v => parseInt(v, 16)))
  (hex.replace('#', ''));

// Luma - https://stackoverflow.com/a/12043228/1762224
const isHexTooDark = (hexColor) =>
  (([r, g, b]) =>
    (0.2126 * r + 0.7152 * g + 0.0722 * b) < 40)
  (hexToRgb(hexColor));

// Brightness - https://stackoverflow.com/a/51567564/1762224
const isHexTooLight = (hexColor) =>
  (([r, g, b]) =>
    (((r * 299) + (g * 587) + (b * 114)) / 1000) > 155)
  (hexToRgb(hexColor));

console.log(isHexTooDark('#222'));  // true
console.log(isHexTooLight('#DDD')); // true

Related