15

Using jQuery (or just JavaScript), how do I detect the inherited background-color of an element?

For example:

<div style="background-color: red">
    <p id="target">I'd like to know that the background-color here is red</p>
</div>

However:

$('#target').css('background-color') == rgba(0,0,0,0)

and

$('#target').css('backgroundColor') == rgba(0,0,0,0)

I'm asking for a general solution. $('#target').parent().css('background-color') would work in this instance, but not all.

Zze
  • 18,229
  • 13
  • 85
  • 118
David Smith
  • 38,044
  • 11
  • 44
  • 61

6 Answers6

11

This could be accomplished by using the parent() in a loop until you reach the body tag:

I've set up a quick jsfiddle site with a little demo based on your code.

Edit: Good catch fudgey. After doing some testing it appears that IE7 will return 'transparent' instead of the rgba(0,0,0,0) value. Here's an updated link which I tested in IE7, Chrome 7, and Firefox 3.6.1.2. Another caveat with this approach: Chrome/Firefox will return rgb(255,0,0); IE returned 'red'.

Community
  • 1
  • 1
David Ipsen
  • 1,513
  • 1
  • 15
  • 22
  • David, Thank you for your code! This is the approach I'm looking at right now. I just find it hard to believe that there isn't a more direct and reliable way to determine this, and as another user pointed out, there is no guarantee that an element is positioned on top of its parent. – David Smith Nov 23 '10 at 19:31
  • 1
    I was getting an alert of "transparent", try changing it to `color !== 'transparent'` - then I get an alert of `rgb(255, 0, 0)` - updated demo: http://jsfiddle.net/Mottie/Y4uDL/1/ – Mottie Nov 23 '10 at 20:12
  • but what if background color is actually rgba(0, 0, 0, 0) and the parent is green?? Your solution won't work – Toolkit Oct 04 '16 at 19:15
9

You can make use of window.getComputedStyle() to get the inherited value.

Caveat: You must manually declare the inheritance in css or inline.

#target{
  background-color: inherit;
}

Working example:

let bgc = window.getComputedStyle($('#target')[0],null).getPropertyValue("background-color");
console.log(bgc);
#target{
  background-color: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div style="background-color: red">
    <p id="target">I'd like to know that the background-color here is red</p>
</div>
Zze
  • 18,229
  • 13
  • 85
  • 118
4

#target has no background color to read because background-color is not inherited.

you could write some javascript that keeps climbing up the DOM tree to search for a background-color declaration until it finds one., but there's no guarantee that that will get you the background color of an element that actually contains your #target.

btw. the css() method gets computed styles, so its giving you the correct reading.

  • You wrote this in as I was trying to figure out why getComputedStyle and currentStyle weren't working for background-color – Ruan Mendes Nov 23 '10 at 19:29
  • Sebastian - Thank you for your answer! I may edit my question's wording, given what I've learned from your answer. – David Smith Nov 23 '10 at 19:33
3

Here's the answer for people who hate browser inconsistency.

As explained, you need to test if this element has a transparent background, then if it does, walk through the DOM until you find a parent with background-color set - but that means testing whatever string each browser chooses to return.

Firefox, IE and others return transparent, Chrome/safari/webkit browsers etc return rgba(0, 0, 0, 0)... and I personally don't trust that there won't be some other exception out there somewhere, now or in the future.

If you don't like the idea of trusting a string given to you by a browser (and you shouldn't), you don't have to: just test against the background-color of an empty element.

Here's a JSBIN example of it in action. (to test on old IE, remove 'edit' from URL)


Usage: Plonk this code somewhere (it works as a jQuery plugin)...

(function($) {
  // Get this browser's take on no fill
  // Must be appended else Chrome etc return 'initial'
  var $temp = $('<div style="background:none;display:none;"/>').appendTo('body');
  var transparent = $temp.css('backgroundColor');
  $temp.remove();

jQuery.fn.bkgcolor = function( fallback ) {
    function test( $elem ) {
        if ( $elem.css('backgroundColor') == transparent ) {
          return !$elem.is('body') ? test( $elem.parent() ) : fallback || transparent ;
        } else {
          return $elem.css('backgroundColor');
        }
    }
    return test( $(this) );
};

})(jQuery);

...then you can get the 'inherited' background colour of any element like this:

var backgroundColor = $('#someelement').bkgcolor();

Or if you want a fallback to be applied instead of 'transparent' if no background-color is set here or anywhere behind this element (e.g. for matching overlays), send as an argument:

var backgroundColor = $('#someelement').bkgcolor('#ffffff');
user56reinstatemonica8
  • 32,576
  • 21
  • 101
  • 125
  • It's 2021 and this is still the best answer, in my opinion. Currently, Firefox and Chrome both return "rgba(0, 0, 0, 0)", but there's no guarantee they will continue to do so. Important to note you will have to append the sample element to the body before trying to compute the background-color. After you've done your checks, you can simply remove it. – David Tran Feb 07 '21 at 03:58
2

Hacky-Recursive answer

jQuery.fn.InheritedBackgroundColor = function(){    
   jQuery(this).parents().each( function(){
      var bc = jQuery(this).css("background-color");
      if( bc == "transparent" ){
         return jQuery(this).InheritedBackgroundColor();
      }
      else{
         return bc;
      }      
   });
}

$(document).ready(function(){
   if( $("#target").InheritedBackgroundColor() == rbga(255,0,0,0) ){
      alert("Win!");
   }
   else{
      alert("FAIL!");
   }

});
TJB
  • 13,367
  • 4
  • 34
  • 46
-1

Here's an elegant way of solving this problem (sorry, I prefer CoffeeScript). It starts from self, but you always can just use $el.parents().each ->.

findClosestBackgroundColor = ($el) ->
    background = 'white'
    $.merge($el, $el.parents()).each ->
      bg = $(this).css('background-color')
      if bg isnt 'transparent' and !/rgba/.test(bg)
        background = bg
        return false
    background

DEMO: Use coffeescript.org to compile this to javascript and run this in a console on any page that has jQuery included.