The Future of CSS: Detect at-rule support with @supports at-rule(@keyword)

In CSS you can do feature detection using @supports. With it you can detect support for property-value pairs and selectors. What currently isn’t possible though, is to detect support for certain at-rules (such as @layer, @scroll-timeline, etc.)

Hot off the press is a new CSS Working Group decision that defines the at-rule function — to be combined with @supports — which will allow just that.


The problem

While working on my articles and demos that use @scroll-timeline, I ran into an issue: how do I feature detect support for this at-rule?

Thankfully I could use a workaround by checking for support of a “telltale” property: animation-timeline: Browsers that have implemented @scroll-timeline, also have implemented the animation-timeline property. By checking for animation-timeline‘s existence, we can feature detect support for @scroll-timeline.

@supports (animation-timeline: works) {
  /* @scroll-timeline compatible code here */ 

But detecting a telltale property isn’t always 100% accurate or possible. Take the wonderful @layer for example: that one doesn’t come with a telltale property. How do we detect support for it?


The solution

To solve this, the CSS Working Group just decided to introduce a new function that be used in conjunction with @supports: at-rule().

With it, we can feature detect at-rule support as follows:

@supports at-rule(@foo) {
  /* @foo is supported */

It’s also possible to detect support for certain descriptors. For @scroll-timeline this will come in handy, as the descriptors changed over time.

@supports at-rule(@foo; desc: val) {
  /* @foo is supported. The descriptor `desc` with value `val` parses as part of that at-rule. */

Winging back to detect support for @layer, the CSS would look like this:

@supports at-rule(@layer) {
  /* @layer is supported */


The solution, bis

Apart from the syntax above, there’s a follow-up issue that will allow you to pass in a full at-rule into at-rule():

@supports at-rule(@foo bar {baz: qux}) {
  /* The entire at-rule with all its descriptors is supported. Unknown descriptors are ignored. */

Note that in this form you’ll have to pass in a valid — thus, complete — at-rule.


Browser Support

This is hot off the press. Currently, no browser supports this. I’ve filed issues at all browser engines to add support for this:


To help spread the contents of this post, feel free to retweet the announcement tweet:


Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.