CSS Reference @rule

@supports

The @supports CSS at-rule allows you to perform feature detection in the browser right from your style sheet instead of resorting to third-party polyfills, such as Modernizr, for example.

Using @supports, you can perform a test and then execute normal CSS rules placed inside the block depending on whether the test returns true or not.

The @supports rule is a conditional group rule whose condition tests whether the user agent supports CSS property:value pairs. This means that, unlike most JavaScript feature detection tools, the @supports rule requires the property and the value specified. For example, a simple @supports declaration looks like this:

/* Applies the rules inside the '@supports' rule only when 'display: flex' is supported. */
@supports (display: flex) {
    .el {
        display: flex;
        align-items: middle;
        /* ... */
    }
}
                

The above example checks whether the browser supports the display property with a value of flex. If it does, that is, if the condition returns true, the style rules declared inside the @supports block will be applied.

The not Keyword

Just like you can check if a feature is supported, you can also check is a feature is not supported, using the not operator. For example, you can combine the above Flexbox support test with another test that provides alternative styles for when Flexbox is not supported.

@supports not (display: flex) {
    .el {
        display: table;
        /* ... */
    }
}
                

Multiple Checks with Multiple Conditions

You can check for multiple feature support in a @supports rule using the and and or operators.

For example, if a certain property is supported with prefixes in some browsers and unprefixed in others, you may want to check for support for any of the prefixed and unprefixed versions. The following example checks for support for Flexbox, including checking for support for vendor-prefixed versions of it.

@supports   (display: -webkit-flex) or
            (display: -moz-flex) or
            (display: flex) {
    .el {
        display: -webkit-flex;
        display: -moz-flex;
        display: flex;
        /* ... */
    }
}
                

You can also check for support for two features in a browser using the and keyword. For example, you may want to check for browser support for CSS 3D transforms and transitions to create some kind of three-dimensional effect:

@supports (transform: rotate3d(1, 1, 0, 30deg)) and (transition: transform 2s) {
    /* do something here */
}
                

You can also combine and and or keywords in one @supports declaration to do multiple feature detections.

To avoid confusion caused by precedence rules, you are now allowed to combine and, or, and not without using layers of parentheses. This means that the following declaration is invalid:

@supports (transform: rotate3d(1, 1, 0, 30deg) and (transition: transform 2s) or (animation: my-3d-animation 2s alternate forwards) {
    /* ... */
}
                

You’re allowed to combine conditionals using parentheses, just like you would with other programming languages, to make precedence clear. So, the above example becomes valid of you do this:

@supports   (transform: rotate3d(1, 1, 0, 30deg) and 
            ( (transition: transform 2s) or (animation: my-3d-animation 2s alternate forwards) ) {
    /* ... */
}
                

Trivia & Notes

Whitespace is required after a not and on both sides of an and or or.

The declaration being tested must always occur within parentheses, when it is the only thing in the expression. For example, the following declaration is invalid:

@supports display: flex {
  /* ... */
}
                

The @supports syntax allows extra parentheses when they are not needed. This flexibility is sometimes useful (for example, when commenting out parts of an expression) and may also be useful for authoring tools. For example, you may write:

@supports ((display: flex)) {
  /* ... */
}
                

If you combine the not operator with the other operators, there is no need to enclose the not between two parenthesis when at the top level. Parentheses are required, however, if it is not the first condition in the declaration.

/* VALID */
@supports not (...) and ((...) or (...)) { /* ... */ }

/* INVALID */
@supports (...) or (...) not (...) { /* ... */ }

/* VALID */
@supports (...) or (...) (not (...)) { /* ... */ }
                

Official Syntax

@supports <supports_condition> {
  /* specific rules */
}
                

Where the support conditions are a set of one or more property:value pairs to be tested. When combining operators, parentheses must be used to make precedence clear.

Examples

The @supports rule can be used in a progressive enhancement workflow to provide extra styles for browsers that supports certain features or CSS properties.

For example, you can provide certain graphical effects to images on a page if the browser supports the filter property. You could then provide normal effect-less images for non-supporting browsers, and apply image filter effects in browsers than do support it:

img {
    /* styles for all browsers */
}
/* styles for browsers that support CSS Filters */
@supports (-webkit-filter: blur(2px)) or (filter: blur(2px)) {
    img {
        filter: blur(2px);
    }
    img:hover {
        filter: blur(0);
    }
}
                

Browser Support

CSS Feature Queries

CSS Feature Queries allow authors to condition rules based on whether particular property declarations are supported in CSS using the @supports at rule.

W3C Candidate Recommendation

Supported from the following versions:

Desktop

  • 28
  • 22
  • No
  • 12
  • 9

Mobile / Tablet

  • 9.0
  • 4.4
  • all
  • 122
  • 123

* denotes prefix required.

  • Supported:
  • Yes
  • No
  • Partially
  • Polyfill

Stats from caniuse.com

Written by . Last updated December 11, 2016 at 9:44 pm by Manoela Ilic.

Do you have a suggestion, question or want to contribute? Submit an issue.