New and Extended Selectors
Learn about new CSS selectors, including, is(), :where(), and :has(), along with others for focus selection and dynamic list styling.
We'll cover the following
Three of the most influential changes to CSS recently have been the :is
, :where
, and :has
pseudo-class selectors. Here’s a summary of them:
:is()
accepts a selector list and equals the specificity of the highest selector. For example,:is(#id, a, .class)
will have the specificity of anid
.:where()
accepts a selector list and always has zero specificity, making it a popular choice for defining baseline styles in resets.:has()
is the long-awaited “parent selector,” which allows checking a parent for a particular child and then styling either the parent or extending into a compound selector to style the children.
Note: Uniquely, both
:is()
and:where()
are also forgiving selectors. This means that, if an invalid selector or a prefixed selector that doesn’t apply is in the list, the rule will continue to work for the valid selectors. This is contrary to standard compound rule definitions like the-webkit-property
property, where browsers that don’t understand-webkit-property
will throw out the whole rule.
The following code utilizes :where()
, :is()
, and :has()
to create an author bio component that changes grid display properties depending on whether or not an avatar is available.
Note: The
:has()
only has partial browser support at the time of writing, so the demo above will currently work in Safari 15.4+ and Chrome/Edge 105+, as well as Firefox 103 with thelayout.css.has-selector.enabled
flag enabled.
Enhanced :not()
selector
The :not()
selector has recently been enhanced to accept a selector list, making :not(nav a, footer a)
valid. However, unlike :is()
and :where()
, the update hasn’t made :not()
forgiving of invalid selectors due to backward compatibility support.
Focus selectors
The next two new pseudo-classes both affect focus behavior. The :focus-within
selector can be used to style a parent when a child is in focus—such as a container around a form field. For element focus styles, we can now use :focus-visible
, which has recently replaced :focus
as the cross-browser default for styling elements that receive focus.
The :focus-visible
pseudo-class makes defined styles visible based on heuristics. Practically speaking, this involves setting focus styles when elements gain focus via keyboard tabbing, but not via mouse clicks.
The ::marker
pseudo-element
Last but not least, the ::marker
pseudo-element allows us to directly select and style list item bullets and numbers on <ul>
and <ol>
elements, as well as the “caret” for the <summary>
element. This means we can use ::marker
to change just a list’s bullet color! There’s a reduced set of allowed properties for styling with ::marker
, and it may not be the best approach, depending on the complexity of a design.