Day 36: :has() and pseudo-elements

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.


We already know that we can select an element based on the presence of a certain child element (in Chrome/Edge 105+ and Safari 15.4+), but there are limitations.

<p>
  <strong>World</strong>!
</p>
p:has(strong) {
  background-color: aqua;
}

World!

This works well with actual elements, but it doesn't work with pseudo-elements.

p::before {
  content: "Hello";
}

p:has(::before) {
  background-color: salmon;
}

World!

According to the spec, that's because Pseudo-elements are generally excluded from :has() because many of them exist conditionally, based on the styling of their ancestors, so allowing these to be queried by :has() would introduce cycles..

For the sake of completeness, of course :has() works with pseudo-classes.

p:has(:hover) {
  background-color: salmon;
}

World!

See on CodePen

Overview: 100 Days Of More Or Less Modern CSS