How to select elements that are not children of other elements in CSS
- Published at
- Updated at
- Reading time
- 2min
Today I came across a PR on MDN compatibility data that aims to update the CSS's support information for the :not()
pseudo-class.
MDN defines :not()
as follows:
The :not() CSS pseudo-class represents elements that do not match a list of selectors.
And before diving into the latest browser additions let's have a look at some examples selectors using :not()
.
/* Select elements that are
not paragraphs */
:not(p) { /* ... */ }
/* Select paragraphs that
don't have the class "fancy" */
p:not(.fancy) { /* ... */ }
/* Select elements that are
not p or span */
:not(p):not(span) { /* ... */ }
/* Select elements that are
not p or span */
:not(p, span) { /* ... */ }
What changed is that the :not()
pseudo-class now has cross-browser support for complex selectors in CSS. What's a complex selector and why is it exciting when using :not()
? Read on!
I started reading the specification for CSS selectors. Reading specifications is never easy, but if you're curious the specification defines a complex selector as follows:
A complex selector is a sequence of one or more compound selectors separated by combinators.
I don't want to get into this topic here, but as far as I understand
or div > span +
are considered complex selectors (please correct me when I'm wrong).
What's exciting about supported complex selectors in :not()
pseudo-classes is that it's possible to select elements that are not (!) children/descendants of other elements using the universal selector (*
).
Let's say that you want to adopt image loading using the webp
or avif
format and want to select (and mark) all the img
elements that are not children of a picture
element, you can now do that! 🤯
In the example above, you see that the img
element that is not a child of a picture
element (and thus is not loading webp
) is displayed with a red border.
Safari supports complex selectors in :not()
since 2015, Firefox supports them since December 2020, and my Chrome just updated and now supports and the Chromiums with version v88, too.
That's a nifty trick I have to say!
Vincent De Oliveira pointed out that you can detect images that are not descendants of picture
elements without a complex :not()
selector: :not(picture) > img
. And they're correct. Thanks for pointing that out!
Join 5.5k readers and learn something new every week with Web Weekly.