Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare colors in JavaScript?

Why doesn't this work? Even though the colour is equal to #ECECF4 it still alerts "No". It is selecting the corrent element as I have tested it. Is there a better way to write this?

<script type="text/javascript">

function weekclick() {
    if (document.getElementById('w1').style.backgroundColor == "#ECECF4") {
        alert("Yes");
    } else {
        alert("No");
    }
}

</script>
like image 943
user1228907 Avatar asked Feb 23 '12 20:02

user1228907


People also ask

How do you compare two colors?

The most common method would be a visual color comparison by looking at two physical color samples side by side under a light source. Color is very relative, so you can compare colors in terms of the other color across dimensions such as hue, lightness and saturation (brightness).

How do you compare two colors in Java?

To compare two Color objects you can use the equals() method : Color « 2D Graphics « Java Tutorial. 16.10.

How are colors represented in JavaScript?

Colors are typically expressed through hexadecimal codes, either prefixed using a pound sign ( # ) or 0x to denote base 16 values. Combining these channels together, we end up with RGB codes, such as: 0xff0000 — Red. 0x00ff00 — Green.


1 Answers

Use a canvas to compare colors.

  • Fill one pixel using the color string
  • and the other pixel using the Element getComputedStyle color property.
  • Compare the two pixels data using Array.from and JSON.stingify

/**
 * Test if Element color property holds a specific color.
 * https://stackoverflow.com/a/60689673/383904
 * 
 * @param {Object} el The DOM Node Element
 * @param {String} prop A CSS property color property
 * @param {String} color A valid CSS color value
 * @return {Boolean} True if element color matches
 */
function isElPropColor(el, prop, color) {
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.fillStyle = color;
  ctx.fillRect( 0, 0, 1, 1 );
  ctx.fillStyle = getComputedStyle(el, null).getPropertyValue(prop);
  ctx.fillRect( 1, 0, 1, 1 );
  const a = JSON.stringify(Array.from(ctx.getImageData(0, 0, 1, 1).data));
  const b = JSON.stringify(Array.from(ctx.getImageData(1, 0, 1, 1).data));
  ctx.canvas = null;
  return a === b;
}


// TEST (PS: see CSS!):

const el   = document.body;
const prop = 'background-color';

console.log(isElPropColor(el, prop, 'red'));      // obviously true :)
console.log(isElPropColor(el, prop, '#f00'));                  // true
console.log(isElPropColor(el, prop, 'rgb(255, 0, 0)'));        // true
console.log(isElPropColor(el, prop, 'hsl(0, 100%, 50%)'));     // true
console.log(isElPropColor(el, prop, 'hsla(0, 100%, 50%, 1)')); // true
body {background: red; }

The buts and whys

Most modern browsers calculate and convert the color value to RGB/A.
But we should not rely on doing strict equality comparison like:

 // (Say the element is really red)
 const isRed = myElement.style.backgroundColor === "rgb(255,0,0)"; // false
  • False because it's actually "rgb(255, 0, 0)", with spaces.
  • No guarantee some browser tomorrow will not convert to "rgba(255, 0, 0, 1)", or HSLA perhaps?
  • Edge and IE will return the value used in CSS or overwritten by our JS

We cannot reliably compare two DIV styles using getComputedStyle

and we cannot even create an "in-memory" DIV element since we need to - append it to the DOM, than use getComputedStyle(tempDIVElement, null).getPropertyValue('background-color') and than remove it from the DOM. It's a waste of DOM recalculations, paints, and it's not guaranteed some wondering stylesheet !important did not messed up our temporary DIV styles div {background: fuchsia !important; } giving false-positives "Is red? True! blue is blue because of !important".

Why canvas?

  • A canvas can stay in memory. No need to append to DOM, set colors, remove element.
  • The returned pixel data is always guaranteed to be [R, G, B, A] (RGBA being 0-255 values)
  • A wondering CSS rule will not mess up the assigned color

Useful links:

  • Canvas_API MDN
  • CanvasRenderingContext2D/getImageData MDN
  • Array/from MDN
  • JSON/stringify MDN
  • Window/getComputedStyle MDN
like image 72
Roko C. Buljan Avatar answered Oct 02 '22 03:10

Roko C. Buljan