Go back to home page of Unsolicited Advice from Tiffany B. Brown

Supporting and detecting @supports

Opera recently added support for the @supports feature of the CSS Conditional Rules Module. Using @supports offers a native way to feature-test support for CSS properties and values.

@supports (display: flex){
    /* Include flexible box styling here */
}

You can also test for negation, and provide rules for cases when a feature is not supported.

@supports not(display: heffalump){
    /* Include not-heffalump styling here */
}

My colleague Chris Mills wrote about the feature for Dev.Opera.

@supports JavaScript API

Opera supports an earlier version of the JavaScript API with the window.supportsCSS() method. Using this method is as simple as passing a property and value.

var hasFlex = supportsCSS('display','flex');

After landing in Opera, the specification changed to add a window.CSS object and supports method instead of window.supportsCSS(). Future syntax will probably be as follows.

var hasFlex = CSS.supports('display','flex');

Testing for @supports support

Of course, this only works when the browser supports @supports. So how do we test for that?

The simplest way I've found takes advantage of the CSS Object Model and its CSSRule interface. @supports extends the CSSRule interface to add the SUPPORTS_RULE constant. In browsers that don't support @supports, its value will be undefined.

function hasAtSupports(){
  return (window.CSSRule !== undefined) && (window.CSSRule.SUPPORTS_RULE !== undefined);
}

I've also published this as a gist.

Using the above method has its limits, however. It will tell you whether @supports is available at all, but cannot be used to detect specific features. For that, try my atsupports.js polyfill (My first polyfill! Please be gentle!), or use Modernizr. The atsupports.js polyfill adds window.CSS.supports to browsers that support @supports but not its JavaScript API. It uses window.supportsCSS() if available. You can see how this works in Opera or Firefox (WebKit support is in a very early stage. Firefox' window.CSS.supports() support is in progress).

Modernizr versus @supports

As Bruce wrote recently, native @supports will perform better than JavaScript. This is true. However, Modernizr offers tests for JavaScript APIs in addition to CSS3. If you're using newfangled HTML5 features in addition to the fancier bits of CSS, Modernizr may be the more prudent choice.