1

In CSS, can you target an element, then exclude instances of it based on parent wrapper elements higher up the DOM?

For example:

HTML

<div class="wrap">
    <ul>
         <li>link</li>
         <li>link</li>
         <li>link</li>
    </ul>
</div>
<ul>
     <li>link</li>
     <li>link</li>
     <li>link</li>
</ul>

CSS

li {
    color:red;
}
li:not(.wrap li) {
    colour:blue;
}

So in this instance, I want to exclude the first series of <li> tags based on their parent wrapper. Is this achievable with CSS? (and I don't mean just target .wrap li and apply the desired styles there, as in my case I have to exclude)

2

1 Answer 1

4

In CSS, can you target an element, then exclude instances of it based on parent wrapper elements higher up the DOM?

No, not the way you seem to be attempting with:

li:not(.wrap li)

You could, though, use instead a more simple approach of styling all <li> elements, and then specifically styling those elements that are descendants of an ancestor with the wrap class-name:

li {
    /* generic styles for <li> elements */
}
.wrap li {
    /* specific styles for <li> elements that are
       descendants of elements with a class of '.wrap' */
}

li {
  color: blue;
}
.wrap li {
  color: red;  
}
<div class="wrap">
    <ul>
         <li>link</li>
         <li>link</li>
         <li>link</li>
    </ul>
</div>
<ul>
     <li>link</li>
     <li>link</li>
     <li>link</li>
</ul>


Note that the following was removed from the above portion of the answer, due to its fragility - having to escape the period in the selector, and the fact that it's open to accidentally being overwritten by any ancestor having the 'wrap' class-name:

:not(\.wrap) li

li {
  color: red;
}
div:not(\.wrap) li {
  color: blue;  
}
<div class="wrap">
    <ul>
         <li>link</li>
         <li>link</li>
         <li>link</li>
    </ul>
</div>
<ul>
     <li>link</li>
     <li>link</li>
     <li>link</li>
</ul>

Sign up to request clarification or add additional context in comments.

1 Comment

For anyone wondering, what escaping the period in \.wrap really does is transform it from a class selector into a type selector. Since an element of one type cannot be another, this makes div:not(\.wrap) similar to div:not(p), i.e. a guaranteed match for all div elements, albeit with slightly increased specificity. The class attribute is completely removed from the equation. If you wrapped the second ul in its own div, the selector would match all li elements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.