How to get computed background color style inherited from parent element
Asked Answered
S

3

14

I have this HTML page:

document.addEventListener("DOMContentLoaded", function (event) {
  var inner_div = document.getElementById("innerDiv");
  console.log(getComputedStyle(inner_div, null)["backgroundColor"]);
});
#outterDiv {
  background-color: papayawhip;
}
<div id="outterDiv">
  <div id="innerDiv">
    I am an inner div
  </div>
</div>

I want to find out the computed background color of the inner div without having to look into parent(s) element's computed style. Is that possible?

Silurid answered 21/9, 2017 at 5:21 Comment(3)
Possible duplicate of How do I detect the inherited background-color of an element using jQuery/JS?Sedillo
No, you cant do it "without having to look into parent(s) element's computed style." as you mentioned. It would be great if DOM has that.Undying
@VamsidharMuggulla I don't know what you mean by "it would be great if the DOM had that". It has nothing to do with the DOM. It's just a natural result of the painting process.Narvaez
D
16

Solution

Here's some vanilla js that will get the effective background color for a given element:

function getInheritedBackgroundColor(el) {
  // get default style for current browser
  var defaultStyle = getDefaultBackground() // typically "rgba(0, 0, 0, 0)"
  
  // get computed color for el
  var backgroundColor = window.getComputedStyle(el).backgroundColor
  
  // if we got a real value, return it
  if (backgroundColor != defaultStyle) return backgroundColor

  // if we've reached the top parent el without getting an explicit color, return default
  if (!el.parentElement) return defaultStyle
  
  // otherwise, recurse and try again on parent element
  return getInheritedBackgroundColor(el.parentElement)
}

function getDefaultBackground() {
  // have to add to the document in order to use getComputedStyle
  var div = document.createElement("div")
  document.head.appendChild(div)
  var bg = window.getComputedStyle(div).backgroundColor
  document.head.removeChild(div)
  return bg
}

Then you can call it like this:

var myEl = document.getElementById("a")
var bgColor = getInheritedBackgroundColor(myEl)

Demo in jsFiddle

Explanation

The solution works by checking the resolved value for a particular element. If the background is transparent, it'll start over again with the element's parent until it finds a defined color or reaches the top.

There are two main concepts to be familiar with:

  1. How background-color is set?
  2. How resolved values work?

According to MDN, background-color has an initial value of transparent and is not an inherited property. Meaning even if a parent div has a color applied, any unstyled child div will have a background-color of transparent. Most browsers, will convert this to an rgb color space so will return the value of rgba(0,0,0,0) with the alpha channel / transparency set to 0%.

This distinction may seem trivial, but it's important to understand that most divs on a page are probably transparent. They do not paint any colors, they just don't mask parent elements. If background values were inherited, colors with transparency would stack and get stronger on child elements

According to MDN, resolved values are what is returned by the browser from .getComputedStyle() which includes computed values and used values. Using the resolved value helps handle special values like inherit, initial, etc. and coverts any relative values to absolute values. Plus also provides a consistent API for getting styling info from attributes vs those applied via stylesheets.

So window.getComputedStyle() isn't used to determine the color that appears in the background; it's just there to get the actual value for the div. And then we'll traverse up the DOM tree until we find an actual value.

Further Reading

Dielu answered 29/6, 2020 at 2:59 Comment(2)
This answer worked excellent for me. I think it should be marked as the answer to the OP's question. I was trying to do exactly the same thing as the OP.Coom
getDefaultBackground will be called a lot of times due to the recursive function. Can be easily fixed by wrapping all of this in another function that first executes getDefaultBackground and passes along the result to the getInheritedBackgroundColor functionSledgehammer
N
5

You apparently mean to ask

How do I find the background color for some element which is used by virtue of that color being set as the background color of some ancestor which shows through because all intervening elements having transparent background color?

However, your question is confusing because you are using the word "inherited", which has a very specific meaning in CSS, which is not relevant here.

The background-color property is not inherited in the CSS sense. Every element has its own background color, which by default is transparent.

The reason that you inner div looks like it has a papayawhip background is that actually it has a transparent background, which lets the papayawhip background of the outer div show through. There is nothing about the inner div that knows or cares about papayawhip, or that can be queried to return papayawhip.

The only way to find that the inner div is going to have a papayawhip background is to traverse the DOM tree and find the closest parent that has a non-transparent background color. This is explained in the question proposed as a dup target.

By the way, what is your underlying problem here? Why are you trying to do this? There are probably better ways.

Narvaez answered 21/9, 2017 at 6:18 Comment(0)
M
4

add background-color: inherit; to your #innerDiv

document.addEventListener("DOMContentLoaded", function (event) {
  var inner_div = document.getElementById("innerDiv");
  console.log(getComputedStyle(inner_div, null)["backgroundColor"]);
});
#outterDiv {
  background-color: papayawhip;
}
#innerDiv {
  background-color: inherit;
}
<div id="outterDiv">
  <div id="innerDiv">
    I am an inner div
  </div>
</div>
Mignonmignonette answered 21/9, 2017 at 5:57 Comment(1)
This will sort of kind of work in the specific case of the inner div being painted by its parent color, but won't help if it's being painted by the background color of some more remote ancestor, which I think is the problem the OP is trying to solve.Narvaez

© 2022 - 2024 — McMap. All rights reserved.