0

I would like to style a class based on another class not existing in the ancestors.

div:not(.evil-class) .element {
  background-color: green;
}
<div class="evil-class">
  <div class="element">An element within the evil class</div>
</div>

<div class="element">An element NOT in the evil class</div>

Not sure why that doesn't work?

I'm aware I can do the inverse; apply a style to both elements and then overwrite that style, but I'd rather not do that as I'd be overwriting styling which could change in a third party lib.

Thanks.

css-applied-despite-rule

Temani Afif
  • 180,975
  • 14
  • 166
  • 216
Dominic
  • 48,717
  • 14
  • 109
  • 126

1 Answers1

6

div:not(.evil-class) .element means "Something with the class element that is descended from a div which does not have the class evil-class"

Your element is not descended from any div, so div:not(.evil-class) doesn't match any of the ancestors (which are only <body> and <html> in this case).


There is currently no way to express "None of the ancestors have a specific class" in CSS.

Selectors Level 4 proposes allowing :not() to contain complex selectors so in the future you may be able to do something like:

.element:not(div.evil-class *) {
  background-color: green;
}
<div class="evil-class">
  <div class="element">An element within the evil class</div>
</div>

<div class="element">An element NOT in the evil class</div>

Browser support is currently almost non-existent, but the demo above works in current versions of Safari.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • Thanks doh! However the issue still stands in my real project which definitely has many divs above it (screenshot attached). Anyway you answered the question as it stands so will mark as correct – Dominic Jan 23 '19 at 17:00
  • @Dominic — Look at the first sentence of this answer again. `div:not(.evil-class)` only has to match **one** ancestor that is both `div` and `:not(.evil-class)`. It doesn't mean that *every* div must not have that class. – Quentin Jan 23 '19 at 17:03