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 an- id.
- :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-propertyproperty, where browsers that don’t understand-webkit-propertywill 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.enabledflag 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.