Treehouse

CSS @supports

By on  

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!

ydkjs-6.png

Recent Features

Incredible Demos

  • MooTools Image Preloading with Progress Bar

    The idea of image preloading has been around since the dawn of the internet. When we didn't have all the fancy stuff we use now, we were forced to use ugly mouseover images to show dynamism. I don't...

  • Xbox Live Gamer API

    My sharpshooter status aside, I've always been surprised upset that Microsoft has never provided an API for the vast amount of information about users, the games they play, and statistics within the games. Namely, I'd like to publicly shame...

  • Spoiler Prevention with CSS Filters

    No one likes a spoiler.  Whether it be an image from an upcoming film or the result of a football match you DVR'd, sometimes you just don't want to know.  As a possible provider of spoiler content, some sites...

Discussion

  1. very nice job. thank you for this great article! I’m looking forward to learn this feature too!

  2. MaxArt

    That’s great news!
    Too bad that the browsers that support @support (hehe) are the ones that support the most of CSS!
    Well, for now. Can be useful in future, hoping that IE11 will add this feature.

  3. Rolf

    Nice standards.. lol.. with Opera doing it differently again (though who is using it anyway today?) I thought now that they’re adopting webkit, that they would use the same standards as others?

    Anyway- this is a nice addition and better than hacks yes, now all we need is IE to update and then every browser should push a silent update.

  4. Mike B

    Ughh, I wish this would end the need for browser prefixes but it looks like you still have to test for them.

  5. PM5544

    Do you have any clue or thought as to why the comma syntax isn’t supported for the “or” in @supports rules?
    Browsers seem to only support “or” to match any of the options around them in @supports but the “normal” media queries only support the “,” syntax and not the “or”.
    I made a quick demo here: http://jsbin.com/ihivow/2/

    It seems a bit counter intuitive to introduce another database like selecting syntax when CSS already has the “,” syntax in media queries.
    The “,” syntax feels more CSSy to me.

  6. Bob

    I’ve been using CSSFix: https://github.com/imsky/cssFx

    It helps me avoid a lot of the ugly browser prefixes code. Thus far, I haven’t run into any issues (knock on wood).

  7. It’s funny cause right now if you wanna use it I think of:

    1- test for its support using Modernizr
    2- if it’s supported you use it to check for support of certain CSS features and place it in CSS
    3- if not supported fall back to Modernizr to add classes to the body
    4- write more CSS to work with older browsers

    I feel like “Yo dawg” … any ideas :D ???

  8. Randy

    I’d like to extend Ahmad’s question and ask: What does the spec say should happen when a back level browser hits one of these rules? Should the contained rules be applied or ignored? Perhaps a question for PPK, but regardless of what the spec says to do, what do browsers actually do?

    • They will ignore it … The syntax is somehow similar media queries block so it will be ignored.

  9. This @supports feature is a new information for me. Thank you for sharing this info.

  10. In your last example you test for prefixed versions of display: flex. But in the code you only use the non-prefixed property. What is the use of the prefixed tests?

  11. Before it was not enabled in Chrome, but it is now:
    https://codereview.chromium.org/13646013

    Hooray!

  12. Eugene OZ

    This tool is great (thank you!), but ugly prefixes still breaks a dream about clean code in CSS.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Use Code Editor