10

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>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
user1228907
  • 369
  • 2
  • 6
  • 16

6 Answers6

16

Comparing colors as part of the business logic should be avoided at all cost.

Instead, keep the logic in JavaScript and act according to a state kept somewhere. Then, if you want to send a visual feedback to the user through a change of color, add a class to the element. That way, JavaScript only knows about class names and the styling is always isolated in the CSS as it should.

$(".list").on("click", "li", function(){
    $(this).toggleClass('active');
});
.list {
  width: 100%;
  padding: 0;
}
.list li {
  padding: 5px 10px;
  list-style: none;
  cursor: pointer;
}
.list li:hover {
  background-color: rgba(0, 0, 0, 0.05);
}
.list li.active {
  background-color: #eeeecc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
  <li>test 1</li>
  <li>test 2</li>
  <li>test 3</li>
</ul>

That being said, OP's code works for me with Chrome 17.0.963.56 and Firefox 8.0. When you don't know what to compare, just use console.log() to see what it looks like.

Note that #ECECF4 is the same color as rgb(236, 236, 244) but in a different representation.

IE7 and IE8 output the HEX value, IE9 and up and other browsers output the RGB format. So comparing color with cross-browser compatibility is a tricky task and the best way to do it isn't beautiful.

I made a simple function which works for most cases with most browser, even with color set through CSS.

function weekclick() {
    var elemColor = getStyle(this, "backgroundColor"),
        color = "rgb(238, 238, 204)";

    console.log("Broswer returned elem color: ", elemColor);

    // IE7 and IE8 output the hex value
    if (elemColor.slice(0, 1) === '#') elemColor = hexToRgb(elemColor);

    console.log(elemColor, " === ", color, "?", elemColor === color);
}

// Source: https://stackoverflow.com/a/41354868/1218980
// Inspired by: https://stackoverflow.com/a/22744598/1218980
function getStyle(el, prop) {
    return (typeof getComputedStyle !== 'undefined' ?
        getComputedStyle(el, null) :
        el.currentStyle
    )[prop];
}


// Slightly modified version to quickly return a string
// https://stackoverflow.com/a/5624139/1218980
function hexToRgb(hex) {
    // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
    var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(shorthandRegex, function(m, r, g, b) {
        return r + r + g + g + b + b;
    });

    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? "rgb(" + [
        parseInt(result[1], 16),
        parseInt(result[2], 16),
        parseInt(result[3], 16)
    ].join(', ') + ")" : null;
}
#css-div {
  background-color: #eeeecc;
}
<div style="Background-color:#eeeecc" onclick="javascript:weekclick.call(this);">#eeeecc</div>
<div style="Background-color:#EEC" onclick="javascript:weekclick.call(this);">#EEC</div>
<div style="background-color:hsla(60, 50%, 86.7%, 1)" onclick="javascript:weekclick.call(this);">hsla(60, 50%, 86.7%, 1)</div>
<div style="background-color:rgb(238, 238, 204)" onclick="javascript:weekclick.call(this);">rgb(238, 238, 204)</div>
<div id="css-div" onclick="javascript:weekclick.call(this);">css</div>

I call the weekclick function with javascript:weekclick.call(this) passing the element itself as the context of the callback, making it easy to access the element with this.

It could be extended to take alpha into account when using HSLA or RGBA.


When I originally wrote this answer back in 2012, I used navigator.appName === "Microsoft Internet Explorer" to know if it was IE7 and the color to compare was changed to its HEX equivalent. Don't do that as it won't work today.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
2

I'm actually just learning javascript, but instead of creating a function that converted rgb() to hex you can create a div of the same background-color you are looking for and compared it to that div's background color. If you happen to already have a div of that hex value you can just do this:

//javascript
if (document.getElementId('desiredElementToCompare').style.backgroundColor === document.getElementId('elementWithTheDesiredHexString').style.backgroundColor)

//jQuery
if ($('#desiredElementToCompare').css('background-color') === $('#elementWithTheDesiredHexString').css('background-color')

You can create a div with a function and then do the comparison like this:

var compareHex = (hex) => {
    var hexString = document.createElement('div')
    hexString.style.backgroundColor = `${hex}`
    return hexString.style.backgroundColor
}
//then compare
//javascript
if (document.getElementId('desiredElementToCompare').style.backgroundColor === compareHex("#ECECF4"))

//jQuery
if($('#desiredElementToCompare').css('background-color') === compareHex("#ECECF4")
Avery Carty
  • 151
  • 2
  • 9
  • 2
    While this works well without much addition to the code, I find it inefficient to grab another element in the page for the sole purpose of comparing their colors. – Emile Bergeron Oct 19 '17 at 22:05
2

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:

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
0

This way suggests using JQuery's background-color which standardises the response to rgb(r, g, b).

How to get the background color of an element using javascript?

Community
  • 1
  • 1
David Newcomb
  • 10,639
  • 3
  • 49
  • 62
0

Maybe this answer could help. Convert the color code to hex and then compare each RGB color/channel (i don't know the word)

https://stackoverflow.com/a/25666938/1757214

I think is better and easy compare two numbers than two strings

Community
  • 1
  • 1
manuerumx
  • 1,230
  • 14
  • 28
-1

I would advice using the '===' stric equal (i think this is the name).

Like:

if (document.getElementById('test').style.backgroundColor === "rgb(236, 236, 244)") {
jribeiro
  • 3,387
  • 8
  • 43
  • 70