David Walsh Blog

CSS @supports

Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn’t been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we do check for CSS property support with JavaScript which leads to brief flashes of content, hopeful code and support, and other problems.  Firefox, Chrome, and Opera have just recently added support for CSS @supports (CSS) and CSS.supports (JavaScript) to detect browser support for a given style directive.  Let’s see how it works!

CSS @supports

CSS @supports directives go in your CSS code just as @media queries do:


@supports(prop:value) {
	/* more styles */
}

CSS @supports allows developers to check style support in a number of different ways.

Basic Property Checks

You can perform basic property and value checks:


@supports (display: flex) {
	div { display: flex; }
}

This is the most basic usage of @supports.

not Keyword

@supports can be paired with a ‘not’ keyword to check for no support:


@supports not (display: flex) {
	div { float: left; } /* alternative styles */
}

Multiple Checks and Conditionals

Multiple CSS property checks can be made via ‘or’ and ‘and’ chaining:


/* or */
@supports (display: -webkit-flex) or
          (display: -moz-flex) or
          (display: flex) {

    /* use styles here */
}

/* and */
@supports (display: flex) and (-webkit-appearance: caret) {
	
	/* something crazy here */
}

You can chain multiple multiple conditionals with parens, just as you can in most other programming languages:


/* and and or */
@supports ((display: -webkit-flex) or
          (display: -moz-flex) or
          (display: flex)) and (-webkit-appearance: caret) {

    /* use styles here */
}

The @supports structure’s conditional pattern matches that of @media‘s conditional pattern.

JavaScript CSS.supports

The JavaScript counterpart to CSS @supports is window.CSS.supports.  The CSS.supports spec provides two methods of usage.  The first method of usage includes providing two arguments: one for the property and another for the value:


var supportsFlex = CSS.supports("display", "flex");

The second usage method includes simply providing the entire string to be parsed:


var supportsFlexAndAppearance = CSS.supports("(display: flex) and (-webkit-appearance: caret)");

Great that you can check CSS support via either method  — it avoids property checking on transient nodes and string-building to check for support.

Before using the JavaScript method of supports, it’s important to detect the feature first.  Opera uses a different method name so that throws things for a bit:


var supportsCSS = !!((window.CSS && window.CSS.supports) || window.supportsCSS || false);

@supports Usage

In most cases, the best usage of @supports is setting an older set of styles as backup and then canceling those styles out and enhancing if a given property is supported.  One brilliant use case for @supports is layout.  Some edge browsers are now providing support for flexbox while others lag behind.  In this case, you could code:


section {
	float: left;
}

@supports (display: -webkit-flex) or
          (display: -moz-flex) or
          (display: flex) {

    section {
      display: -webkit-flex;
      display: -moz-flex;
    	display: flex;
    	float: none;
    }
}

Other good uses cases will pop up as developers have more time to experiment with the new @supports feature.

Enabling @supports

If you want to dabble with new features like @support, you should invest some time installing edge browsers like Canary, Firefox Nightly, and Opera Next.  Opera 12.1, WebKit Nightly, and Firefox Nightly all support @supports.  Old versions of Firefox provide support after [layout.CSS.supports-rule.enabled] is enabled.

@supports is a welcomed addition to the CSS and JavaScript specs.  Feature detection is our number one best practice for feature support and @supports provides a lower level layer than the hacks we’ve been using the past few years.  I suspect we’ll see loads of @support directives over the next few years as flexbox becomes more useful and widely used!