13

Explanation:

I'm not a CSS expert but my current attempt is this.

div:not(.classToBeAvoid) *{
    background-color:red;
}

Which in English I read as...

"Apply a red background to any element which does not have <div class="classToBeAvoid"> as an ancestor".

But nonetheless, in my test, it doesn't seem to work like this.

CodePen:

https://codepen.io/anon/pen/eGVBVb

Code:

<div class="classToBeAvoid">
  <div>
    <p>
      Shouldn't be a red background on any element around here.
    </p>
  </div>
</div>

<div>
 <p>
   Should be a red background
 </p>
</div>

div:not(.classToBeAvoid) *{
  background-color:red;
}
andreas
  • 16,357
  • 12
  • 72
  • 76
Geesh_SO
  • 2,156
  • 5
  • 31
  • 58
  • If you remove the second level of "div" in your first "block", it seems to work as you want it to. – Dexter0015 Oct 06 '17 at 15:29
  • So my code only works for direct descendants of `div`s? Can I make this apply to any descendant? – Geesh_SO Oct 06 '17 at 15:30
  • 3
    It actually reads as "Apply a red background to any element which has any `
    ` which does not `class="classToBeAvoid"` as an ancestor".
    – Quentin Oct 06 '17 at 15:31
  • I can actually see how that makes sense, Quentin. Thanks for letting me know. – Geesh_SO Oct 06 '17 at 15:32
  • Please look into this post [enter link description here](https://stackoverflow.com/questions/9110300/can-i-write-a-css-selector-selecting-elements-not-having-a-certain-class) – Liaqat Saeed Oct 06 '17 at 15:32
  • This will be difficult to accomplish in CSS if you have the p in each div nested to different depths. I would set the default background to red and then for ones that you want to avoid, use the class to determine a different background, like so: https://jsfiddle.net/td8b0r26/ – TylerH Oct 06 '17 at 15:35
  • Possible duplicate of [CSS negation pseudo-class :not() for parent/ancestor elements](https://stackoverflow.com/questions/7084112/css-negation-pseudo-class-not-for-parent-ancestor-elements) – TylerH Oct 06 '17 at 17:34

1 Answers1

10

Your interpretation is totally correct. You are applying a red background to any <div> that is not of class classToBeAvoid. Unfortunately this also applies to child <div>s, which is the reason for your first <div> to also be red (in fact your first parent <div> isn't red, but its child).

There are several ways to solve this issue (at least with some trade-offs).


1. The general siblings selector ~

You can use the general siblings selector, which will work in your case, because your .classToBeAvoid is before the following <div> elements.

div~:not(.classToBeAvoid)

div~:not(.classToBeAvoid) {
  background-color: red;
}
<div class="classToBeAvoid">
  <div>
    <p>
      Shouldn't be a red background on any element around here.
    </p>
  </div>
</div>


<div>
  <p>
    Should be a red background
  </p>
</div>

2. No nesting

If thats not always the case (which I assume), one way would be to remove your <div> nesting to make it work.

div:not(.classToBeAvoid) {
  background-color: red;
}
<div class="classToBeAvoid">
  <p>
    Shouldn't be a red background on any element around here.
  </p>
</div>


<div>
  <p>
    Should be a red background
  </p>
</div>

3. Additional class

If you don't want to remove your <div> nesting either, you can apply classes to the top level <div>s and use these for the selector, i.e.:

.chosen:not(.classToBeAvoid)

.chosen:not(.classToBeAvoid) {
  background-color: red;
}
<div class="chosen classToBeAvoid">
  <div>
    <p>
      Shouldn't be a red background on any element around here.
    </p>
  </div>
</div>


<div class="chosen">
  <p>
    Should be a red background
  </p>
</div>

4. Direct child selector >

If you also don't want to give every top level <div> an additional class, you can use the parent with the direct child selector >:

body>div:not(.classToBeAvoid)

body>div:not(.classToBeAvoid) {
  background-color: red;
}
<div class="classToBeAvoid">
  <div>
    <p>
      Shouldn't be a red background on any element around here.
    </p>
  </div>
</div>


<div>
  <p>
    Should be a red background
  </p>
</div>

5. Inheritance

Furthermore you can use your selector div:not(.classToBeAvoid) as you already did and in addition make sure, that child <div>s inherit the behaviour of .classToBeAvoid:

.classToBeAvoid div {
  background-color: inherit;
}

div:not(.classToBeAvoid) {
  background-color: red;
}
.classToBeAvoid div {
  background-color: inherit;
}
<div class="classToBeAvoid">
  <div>
    <p>
      Shouldn't be a red background on any element around here.
    </p>
  </div>
</div>


<div>
  <p>
    Should be a red background
  </p>
</div>

  1. or 5. are what I would prefer in your case.
andreas
  • 16,357
  • 12
  • 72
  • 76