Evan Hobbs
Evan Hobbs

Reputation: 3672

How to get effective background color of transparent element with javascript/jQuery

Basically, I have an element on the page that may be inserted in multiple different locations. It has no background color set but depending on the background color of where it's inserted I may want to make a couple of changes to it.

My question is: how to get the effective background-color for an element even if that background-color may have been inherited from a parent (potentially all the way to body).

Here's a simplified example where I would like to find the background-color of .color-me

<div class="cont">
   <div class="color-me">what's my background-color?</div>
</div>

And a codepen: http://codepen.io/evanhobbs/pen/FbAnL/

Upvotes: 8

Views: 4493

Answers (3)

Eugene Lyushenko
Eugene Lyushenko

Reputation: 7

Here's an elegant way of solving this problem (sorry, I prefer CoffeeScript). It starts searching 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.

Compiled code:

var findClosestBackgroundColor;

findClosestBackgroundColor = function($el) {
  var background;
  background = 'white';
  $.merge($el, $el.parents()).each(function() {
    var bg;
    bg = $(this).css('background-color');
    if (bg !== 'transparent' && !/rgba/.test(bg)) {
      background = bg;
      return false;
    }
  });
  return background;
};

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074385

This is possible given some (pretty major) caveats. zzzzBov summed them up well in a comment on the question:

... the complexity comes in when you need to start taking into account background images, gradients, rgba values, and opacity. It's relatively simple to get the color of the nearest parent with a non-transparent background color, it just might not be the actual color behind the element.

With those caveats in place, basically you have to get the background color of the element and, if it's transparent, go to the parent element, and so on.

Different browsers have different views of "transparent", here's an example covering most of them: Updated Pen

$(function() {
  var bc;
  var $elm = $(".color-me");
  while (isTransparent(bc = $elm.css("background-color"))) {
    if ($elm.is("body")) {
      console.log("Gave up");
      return;
    }
    $elm = $elm.parent();
  }
  console.log("Effective color: " + bc);

  function isTransparent(color) {
    switch ((color || "").replace(/\s+/g, '').toLowerCase()) {
      case "transparent":
      case "":
      case "rgba(0,0,0,0)":
        return true;
      default:
        return false;
    }
  }
});

I'm not at all sure this is possible with all browsers, particularly not ones that give back an rgb (not rgba) value for the computed color.

Upvotes: 7

JF it
JF it

Reputation: 2403

I much prefer jsfiddle but here is your updated codepen.. http://codepen.io/anon/pen/nhDGC Added anonymous function so to use it just call $('.yourselector').getBg();

jQuery.fn.getBg = function() {
return $(this).parents().filter(function() {

    var color = $(this).css('background-color');

    if(color != 'transparent' && color != 'rgba(0, 0, 0, 0)' && color != undefined) 
    { return color; 
    }
}).css('background-color');
};

$(function() {
  //console.log($('.cont').css('background-color'));
   console.log($('.color-me').getBg())
   $('.color-me').append($('.color-me').getBg());

   console.log($('.color-me2').getBg())
   $('.color-me2').append($('.color-me2').getBg());
 });

It filters parents + will return when it finds the background color existing.

Upvotes: 3

Related Questions