Imagine that the HTML and CSS below is already set.
What CSS rules can I add beneath the already-written CSS to make the red paragraphs display as red?
body,
div {
display: flex;
flex-wrap: wrap;
}
p {
margin: 6px;
}
.one-filter-one p,
p[class^="one-filter-one"] {
color: blue;
}
.two-filter-two p,
p[class^="two-filter-two"] {
color: green;
}
.four-filter-four p,
p[class^="four-filter-four"] {
color: orange;
}
<p class="another-class">This is red.</p>
<p>This is red.</p>
<div class="one-filter-one">
<p>This is blue.</p>
<p class="one-filter-one--paragraph">This is blue.</p>
</div>
<p class="two-filter-two">This is green.</p>
<p>This is red.</p>
<p class="another-class-two">This is red.</p>
<div class="three-filter-three">
<p>This is unstyled (black).</p>
<div><p>This is unstyled (black) too.</p></div>
</div>
<div class="four-filter-four">
<p class="four-filter-four--sentence">This is orange.</p>
</div>
<p class="five-filter-five">This is also unstyled (black).</p>
<div class="another-class-three">
<p>This is red.</p>
<p class="another-class-four">This is red.</p>
</div>
My best guess is to use the :not() pseudo-class.
But I'm not entirely convinced this is the right approach, principally because I'm not sure that :not() can handle this case.
My attempt at a solution, using :not():
body,
div {
display: flex;
flex-wrap: wrap;
}
p {
margin: 6px;
}
.one-filter-one p,
p[class^="one-filter-one"] {
color: blue;
}
.two-filter-two p,
p[class^="two-filter-two"] {
color: green;
}
.four-filter-four p,
p[class^="four-filter-four"] {
color: orange;
}
p:not([class*="-filter-"]) {
color: red;
}
<p class="another-class">This is red.</p>
<p>This is red.</p>
<div class="one-filter-one">
<p>This is blue.</p>
<p class="one-filter-one--paragraph">This is blue.</p>
</div>
<p class="two-filter-two">This is green.</p>
<p>This is red.</p>
<p class="another-class-two">This is red.</p>
<div class="three-filter-three">
<p>This is unstyled (black).</p>
<div><p>This is unstyled (black) too.</p></div>
</div>
<div class="four-filter-four">
<p class="four-filter-four--sentence">This is orange.</p> </div>
<p class="five-filter-five">This is also unstyled (black).</p>
<div class="another-class-three">
<p>This is red.</p>
<p class="another-class-four">This is red.</p>
</div>
Clearly this is not it, because I am not correctly selecting:
NOT descendant elements of [class*="-filter-"].
But I'm not clear how to do this at all.
Is there any way to do this, or am I looking to achieve the impossible in 2020, given CSS's contemporary capabilities?
Notes:
Although, in 2020, the pseudo-class :not() has been around for the best part of a decade I've always tended to avoid using it. The only thing I do know is that the :not() pseudo-class function can only take simple (ie. not compound) selectors.
Added:
Based on @G-Cyrillus' brilliant suggestion (in the comments, immediately below), I have come up with the following:
body > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]),
body > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > :not([class*="-filter-"]) > p:not([id*="-filter-"]):not([class*="-filter-"]) {
color: red;
}
On the plus side this does work. (So, infinitely better than anything I had before).
On the minus side:
- it's verbose
- it's inelegant
- it only works to the fourth level of element-nesting
- I can of course carry on adding levels, but that only makes it verboser and ineleganter