Testing selector support with @supports

Text reads @supports selector()

While updating the Conditional CSS chapter of CSS Master, I encountered a new-to-me feature of the CSS Conditional Rules Module: the selector() function.

You may be familiar with the Conditional Rules Module, the specification that defines, @supports and the CSS.supports() API. With @supports, you can add CSS rules that the browser applies only when it supports a particular property and value. For example, you might add styles that only apply when the browser supports masonry layouts for CSS Grid.

@supports ( grid-template: masonry / repeat(6, 1fr) ) {
  .grid {
    display: grid;
    gap: 1rem;

    /* Short hand for grid-template-rows / grid-template-columns */
    grid-template: masonry / repeat(6, 1fr);
  }
}

The level 4 draft of the Conditional Rules specification extends the @supports rule so we can also conditionally apply rules based when the browser supports a particular selector.

Selectors Level 4, for example, added an optional, of S clause to the definition of the :nth-child()/:nth-last-child() pseudo-classes. To date, however, few browsers support it. Using the selector() function with @supports lets us apply CSS in those browsers that do.

@supports selector( path:nth-child(2 of .hex) ) {
  path:nth-child(2 of .hex) {
    fill: magenta;
  }
}

The selector() function accepts a selector as an argument. As with other @supports conditions, you do not need to enclose it in quotes.

Browser support for selector() is widespread and implementations are pretty consistent across browsers, even though the specification is a work in progress. Whether you need to use the @supports selector(), however, is a tougher call.

According to the rules of CSS parsing and error handling, browsers ignore rules that they don't understand. If a browser doesn't support a selector, the ruleset won't be applied. With that in mind, you may find it more useful to use @supports selector() with the negation keyword to apply styles when a selector is not supported.

@supports not selector( path:nth-child(2 of .hex) ) {
  path:nth-child( 3 ) {
    fill: magenta;
  }
}

Testing selector() support with DOM Scripting

The @supports at-rule has a corresponding API, that you can also use with the selector() function.

const supportsOfS = CSS.supports( 'selector( path:nth-child(2 of .hex)' );

When using selector() with CSS.supports(), enclose the entire clause in quotation marks. Otherwise the script parsing engine will misinterpret selector as a JavaScript function. You'll get a ReferenceError.

Get CSS Master, third edition

Cover image of CSS Master, second edition Did you learn something from this blog post? You might like the third edition of CSS Master. It contains several nuggets of CSS joy like this one.

Buy now from SitePoint

Subscribe to the Webinista (Not) Weekly

A mix of tech, business, culture, and a smidge of humble bragging. I send it sporadically, but no more than twice per month.

View old newsletters