How to write a :not() CSS exclusion working in every cases?

78 views Asked by At

I am trying to exclude some CSS rules when there is a defined CSS class as a parent with this rule:

.cc div:not(.cc-ei) li { color: red; }

But it doesn't work for all cases, as you can see in the code below, and the linked Codepen demo:

.item {
  color: green;
}

.cc div:not(.cc-ei) li {
  color: red;
}
<div class="cc">
  <div>
    <ul>
      <li>Should be red</li>
    </ul>
  </div>

  <div class="cc-ei">
    <ul>
      <li class="item">Should be green</li>
    </ul>
  </div>

  <div class="toto">
    <div class="cc-ei">
      <ul>
        <li class="item">Should be green</li>
      </ul>
    </div>
  </div>
</div>

How could I define the rule .cc li { color: red; } to exclude <li> that are in <div class="cc-ei">?

3

There are 3 answers

0
isherwood On

Logically your selector looks for list items in any div without the class. Since your list is nested in multiple divs, one without the class, that condition supersedes. You can specify a child relationship (as opposed to a general descendant relationship) to get it to work.

.item {
  color: green;
}

.cc div:not(.cc-ei)>ul li {
  color: red;
}
<div class="cc">
  <div>
    <ul>
      <li>Should be red</li>
    </ul>
  </div>

  <div class="cc-ei">
    <ul>
      <li class="item">Should be green</li>
    </ul>
  </div>

  <div class="toto">
    <div class="cc-ei">
      <ul>
        <li class="item">Should be green</li>
      </ul>
    </div>
  </div>
</div>

1
David Thomas On

The easiest way to achieve your requirements is to simply use the following rule, to style the <li> elements:

li:not(.cc-ei li) {
  color: red;
}

The revised code is below, with explanatory comments:

body {
  font: 700 16px/1.5 Arial;
}

.item {
  color: green;
}

/*
  we select all <li> elements that do not match the selector
  passed to the :not() pseudo-class. This eliminates all
  <li> elements that are descendants of an ancestor element
  with the class of "cc-ei":
*/
li:not(.cc-ei li) {
  color: red;
}
<div class="cc">
  <div>
    <ul>
      <li>Should be red</li>
      <li>Should be red</li>
      <li>Should be red</li>
    </ul>
  </div>

  <div class="cc-ei">
    <ul>
      <li class="item">Should be green</li>
      <li class="item">Should be green</li>
      <li class="item">Should be green</li>
    </ul>
  </div>

  <div class="toto">
    <div class="cc-ei">
      <ul>
        <li class="item">Should be green</li>
        <li class="item">Should be green</li>
        <li class="item">Should be green</li>
      </ul>
    </div>
  </div>
</div>

References:

0
Heretic Monkey On

Simple as the author (me). Just tell it what you want: li items within .cc-ei should be green.

.item {
  color: green;
}

.cc li {
  color: red;
}

.cc-ei li {
  color: green;
}
<div class="cc">
  <div>
    <ul>
      <li>Should be red</li>
    </ul>
  </div>

  <div class="cc-ei">
    <ul>
      <li class="item">Should be green</li>
    </ul>
  </div>

  <div class="toto">
    <div class="cc-ei">
      <ul>
        <li class="item">Should be green</li>
      </ul>
    </div>
  </div>
</div>