CSS Inherit for unknown Background Color is Actually Transparent
Asked Answered
P

2

35

I am creating a tab-like functionality with <ul> and <li> elements, and I noticed this kind-of unexpected behavior with CSS background-color: inherit.
One would expect that inherit wouldn't actually mean transparent, but rather child.background-color == parent.background-color (forgive the pseudo-code).

My code is quite simple, but I have a problem: I'm developing for variable conditions. That means I could never know what background-color will be used with my code, and I don't want to introduce my own.

I have prepared a JSFiddle, in which the background is randomly set on page load, to imitate the randomness of my code's destination. The obvious problem is that the active tab looks awful with its background-color pre-set. So, I changed it to background-color: inherit. (see JSFiddle 2)

While this obviously solved the background issue, the border of the element below (cg_content) started showing again, because the inherit property, acts like transparent, instead of what it does when there is a set background-color.

Question is: Is there a way to make it inherit the actual background-color without Javascript?
If not, could you suggest a better way to make these tabs look good without pre-set colors?

P.S.: The content <div> should not be a child element of the <li> elements, as these tabs share some contents.
P.S.2: I can't make it any more clear, that I obviously know how to do this with JS. I just don't want to.

Prosecute answered 27/10, 2013 at 9:40 Comment(2)
My solution, if you only need a non-transparent bg that wont clash with the text color: On the parent and child elements, I used a combination of currentColor and filter : invert, contrast, brightness, and sometimes grayscale. This tricks works well with dynamic theming on light, dark or even coloured themes without explicitly specifying any colour values.Boiardo
Hi @JoeDF, it sounds very interesting! I think it doesn't directly answer the question however, because this question was about unknown environments, but feel free to post your comment as an answer, because I think it may help other readers!Prosecute
E
59

Setting background-color: inherit does cause it to take the background colour of the parent element.

The reason it is taking transparent is because the background colour of the parent (the li) is transparent (the default value).

The only other element in your second JSFiddle which has a background colour set is #unknown_background, which is the anchor's great-great-grandparent.

Add div, ul, li { background-color: inherit; } to the end of your stylesheet and the background will be inherited all the way down and the border will not show up.

Erogenous answered 27/10, 2013 at 9:45 Comment(5)
I would also advise to get rid of the container div for the ul. Removing it does not change the outcome at all and you do not have to generate a new css rule and another element with an id.Honorarium
Thank you @Quentin. That is indeed a solution to the simplified version of my code. But in the real-world example, my code may be part of a great-great grandchild of the element with the actual background-color, and I have no CSS control to the elements in between. Any idea with that?Prosecute
There is no way, in CSS, to get an element to take its background from some arbitrary other element (or even ancestor). You can either be specific or you can inherit from the parent.Erogenous
Thanks Quentin. I'll wait and see if anyone comes up with an idea on how to make the tabs work without pre-set colors.Prosecute
Is there no other way to do that? What if I have a position: sticky element somewhere and want its background to be on top of everything? Write background-color: inherit for 30 levels a deep nested element? :-/Cosmopolite
B
7

Posting this as suggested by @mavrosxristoforos, kudos! This is less of an answer and more to add on to the information that is available here. Hopefully, this useful to some people out there.

If you only need a non-transparent background that won't clash with the text color, but is still very visible: my solution involves using a combination of currentColor and filters such as invert, contrast or brightness on the parent and child elements.

This tricks works well with dynamic theming such as light, dark or even colored themes without explicitly specifying any color values for these elements. This can be used with some existing CSS themes that don't have things defined with CSS variables or have missing classes to change only a particular color conditionally. Observe the demo below.

var root = document.documentElement;
var themeDark = true;

updateTheme( themeDark );

$('.card').on('click', function(){
  themeDark = !themeDark; // switch the theme
  updateTheme(themeDark);
});

function updateTheme(useDarkTheme){
  if (useDarkTheme) {
      root.style.setProperty('--primary','#000');
      root.style.setProperty('--secondary','#333');
      root.style.setProperty('--ternary','#eee');
    } else {
      root.style.setProperty('--primary','#efefef');
      root.style.setProperty('--secondary','#ddd');
      root.style.setProperty('--ternary','#333');
    }
}
/* say you're using a bootstrap theme with some defined colors, 
 * but you want to customize some colors of some elements which
 * have colors defined without CSS variables that you could 
 * have used.
 */

body {
  font-family: sans-serif; font-size: 14px;
  color: var(--primary);
  background: var(--secondary);
  }

.card {
  border: 1px solid #666; border-radius: 6px;
  padding: 1em; margin: 1em;
  user-select: none; cursor: pointer;
  background: var(--ternary);
  }

.card h2 {
  font-size: 24px;
  color: var(--primary);
  }

.card-body {
  border-radius: 6px;
  background: currentColor;
  }

.card-body p { padding: 1em; }

.card-body, .card-body p { filter: invert(1) contrast(1.2) brightness(0.8); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="card">
  <h2>Title</h2>
  <div class="card-body">
    <p><b>Click to toggle the theme.</b> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
  </div>
</div>
Boiardo answered 19/12, 2020 at 3:19 Comment(2)
Thanks for sharing Joe! CSS has gone a long way since 2013 that this question was originally posted!Prosecute
@Prosecute So true!Boiardo

© 2022 - 2024 — McMap. All rights reserved.