Day 50: :has(:not()) vs. :not(:has())
posted on
It’s time to get me up to speed with modern CSS. There’s so much new in CSS that I know too little about. To change that I’ve started #100DaysOfMoreOrLessModernCSS. Why more or less modern CSS? Because some topics will be about cutting-edge features, while other stuff has been around for quite a while already, but I just have little to no experience with it.
Something I was tripping over when I began learning about :has()
was the combination with :not()
.
Let me show you what I got wrong by using an example. Let's say we have two cards, each with a heading and some text. One of them also contains an image.
<div class="card">
<h2>Card with image</h2>
<img src="https://assets.codepen.io/144736/skateboard.jpg" alt="" />
<p>text</p>
</div>
<div class="card">
<h2>Card without image</h2>
<p>text</p>
</div>
Card with image
text
Card without image
text
Now we want to add additional styling to cards without an image. If a card doesn't contain an image, we want to remove the margin on the heading and change the border-style.
.card:has(:not(img)) {
border-style: dotted;
}
.card:has(:not(img)) h2 {
margin-top: 0;
}
Card with image
text
Card without image
text
The styles apply to both cards, no matter whether an image is present. That's because .card:has(:not(img))
means “select a .card
that has any element that is not an image”. This means that the selector only wouldn't apply if the card only contained images.
<div class="card">
<img src="https://assets.codepen.io/144736/skateboard.jpg" alt="" />
</div>
If we switch :has()
and :not()
we're instructing the browser to do something completely different. .card:not(:has(img))
means “select a .card
doesn't have (not has) an image”, and that's exactly what we want in this case.
.card:not(:has(img)) {
border-style: dotted;
}
.card:not(:has(img)) h2 {
margin-top: 0;
}
Card with image
text
Card without image
text
Further reading
- Day 6: the :has() pseudo-class
- Day 8: nesting :has()
- Day 16: the specificity of :has()
- Day 26: using combinators in :has()
Overview: 100 Days Of More Or Less Modern CSS