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
- 131
- 132