Reputation: 2206
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;
}
Upvotes: 13
Views: 5936
Reputation: 16946
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).
~
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>
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>
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>
>
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>
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>
Upvotes: 10