TJBlackman
TJBlackman

Reputation: 2313

Determine Color Lightness via RGB

I have some color swatches that should show the rgb value of the color displayed, with the background being the actual color. Then, if the color in question is light-ish, the text should be black, and if the color in question is dark-ish, the text color should be white.

How can I detect if the RGB value is light-ish or dark-ish??

JS FIDDLE

<style>
#preview {
  display: block; 
  height: 40px; 
  line-height: 40px; 
  font-size: 20px; 
  vertical-align: middle;
  width: 150px; 
  text-align: center; 
}
</style>

<!-- html -->
<button id="new_color">Try Random Color</button>
<p id="preview">Click the button!</p>

<script>
const getRandNum = () => Math.floor(Math.random() * 256);

const get_random_color = () => (`rgb(${getRandNum()}, ${getRandNum()}, ${getRandNum()})`);

const checkColor = (color) => {
    // color = 'rgb(x, y, z)'; 
    // check color is light
    // or color is dark
    return true; 
}

$('#new_color').click(function(){
    const p = $('#preview');
    const bg_color = get_random_color(); 
    const color_is_light = checkColor( bg_color ); 

    const text_color = color_is_light ? 'black' : 'white';

    p.css({
        color: text_color,
        backgroundColor: bg_color
    })
});
</script>

I only found solutions for #hex colors, but not for rgb. Any help is very much appreciated.

Upvotes: 3

Views: 2433

Answers (3)

vrintle
vrintle

Reputation: 5586

You have to check if(red + green + blue >= 255 * 1.5) for a light color as said by the second answer in this post

const checkColor = (color) => {
    // extract values of red, green and blue from color
    let clrarr = color.match(/\d+/g).map(num => +num);

  if(clrarr[0] + clrarr[1] + clrarr[2] >= 255 * 3 / 2) 
    return true; // color is light

  return false; // color is dark
}

JSFiddle

Upvotes: 0

Ateş G&#246;ral
Ateş G&#246;ral

Reputation: 140032

If you're looking for relative luminance, a quick formula you can use is:

Y = 0.2126R + 0.7152G + 0.0722B

Source: https://en.wikipedia.org/wiki/Relative_luminance

To be able to use the coefficients above directly, you'll have to either normalize your RGB components to 1. Or divide by 255 first. The Y value you'll get is between 0-1, so you can probably then do:

const color_is_light = y > 0.5;

I'd do something like:

const getRandomRgb = () => [
  Math.random(),
  Math.random(), 
  Math.random()
];

const getRelativeLuminance = (rgb) =>
  0.2126 * rgb[0]
  + 0.7152 * rgb[1]
  + 0.0722 * rgb[2];

const getCssColor = (rgb) => `rgb(${rgb.map((c) => c * 255)}`;

Though, there'll literally be a "gray area" where you will not get enough contrast with either white or black text against a mid-gray background.

You may want to change your get_random_color function to return the individual components, do the math above, and then construct the CSS color value afterwards.

Upvotes: 4

Marc Sloth Eastman
Marc Sloth Eastman

Reputation: 801

So if you have answers for hex, adapt those for RGB because the hex values are just the base 16 numbers of the rgb base 10 values. Looking for a way to convert between bases now.

EDIT: If your r value in hex is "5a", the way to get that r value in base 10 for rgb() is parseInt("5a",16)

EDIT2: To get the hex value from decimal, this works: const hex = d => Number(d).toString(16).padStart(2, '0') ~ taken from How to convert decimal to hex in JavaScript?

Upvotes: 0

Related Questions