@supports CSS at-rule

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.

The @supports CSS at-rule lets you specify CSS declarations that depend on a browser's support for CSS features. Using this at-rule is commonly called a feature query. The rule must be placed at the top level of your code or nested inside any other conditional group at-rule.

In JavaScript, @supports can be accessed via the CSS object model interface CSSSupportsRule.

Try it

.flex-container > * {
  padding: 0.3em;
  list-style-type: none;
  text-shadow: 0 0 2px red;
  float: left;
}

@supports (display: flex) {
  .flex-container > * {
    text-shadow: 0 0 2px blue;
    float: none;
  }

  .flex-container {
    display: flex;
  }
}
<ul class="flex-container">
  <li><a href="#">Index</a></li>
  <li><a href="#">About me</a></li>
  <li><a href="#">Contact</a></li>
</ul>

Syntax

css
@supports (<supports-condition>) {
  /* If the condition is true, use the CSS in this block. */
}

@supports (<supports-condition>) and (<supports-condition>) {
  /* If both conditions are true, use the CSS in this block. */
}

The @supports at-rule consists of a block of statements with a supports condition. The conditions can be combined by conjunctions (and), disjunctions (or), and/or negations (not). The precedence of operators can be defined with parentheses.

Supports conditions can use either a <property>: <value> declaration syntax or a <function()> syntax. The following sections describe the use of each type of supports condition.

Declaration syntax

The declaration syntax checks if a browser supports the specified <property>: <value> declaration. The declaration must be surrounded by parentheses. The following example returns true if the browser supports the expression transform-origin: 5% 5%:

css
@supports (transform-origin: 5% 5%) {
}

Function syntax

The function syntax checks if a browser supports values or expressions within the function. The functions supported in the function syntax are described in the following sections.

selector()

This function evaluates if a browser supports the specified selector syntax. The following example returns true and applies the CSS style if the browser supports the child combinator:

css
@supports selector(h2 > p) {
}

font-tech()

This function checks if a browser supports the specified font technology for layout and rendering. The following example returns true and applies the CSS style if the browser supports the COLRv1 font technology:

css
@supports font-tech(color-COLRv1) {
}

The table below describes the font technologies (<font-tech>), including color font technologies (<color-font-tech>), font feature technologies (<font-features-tech>), and other available font technologies that can be queried using the font-tech() function:

Technology Supports
<color-font-tech>
color-colrv0 Multi-colored glyphs via COLR version 0 table
color-colrv1 Multi-colored glyphs via COLR version 1 table
color-svg SVG multi-colored tables
color-sbix Standard bitmap graphics tables
color-cbdt Color bitmap data tables
<font-features-tech>
features-opentype OpenType GSUB and GPOS tables
features-aat TrueType morx and kerx tables
features-graphite Graphite features, namely Silf, Glat, Gloc, Feat, and Sill tables
Other <font-tech> values
incremental-patch Incremental font loading using the patch subset method
incremental-range Incremental font loading using the range request method
incremental-auto Incremental font loading using method negotiation
variations Font variations in TrueType and OpenType fonts to control the font axis, weight, glyphs, etc.
palettes Font palettes by means of font-palette to select one of many color palettes in the font

font-format()

This function checks if a browser supports the specified font format for layout and rendering. The following example returns true and applies the CSS style if the browser supports the opentype font format:

css
@supports font-format(opentype) {
}

The following table describes the available formats (<font-format> values) that can be queried with this function:

Format Description File extensions
collection OpenType Collection .otc, .ttc
embedded-opentype Embedded OpenType .eot
opentype OpenType .ttf, .otf
svg SVG Font (deprecated) .svg, .svgz
truetype TrueType .ttf
woff WOFF 1.0 (Web Open Font Format) .woff
woff2 WOFF 2.0 (Web Open Font Format) .woff2

The not operator

The not operator precedes an expression resulting in the negation of the expression. The following returns true if the browser's transform-origin property considers 10em 10em 10em to be invalid:

css
@supports not (transform-origin: 10em 10em 10em) {
}

As with any operator, the not operator can be applied to a declaration of any complexity. The following examples are both valid:

css
@supports not (not (transform-origin: 2px)) {
}
@supports (display: grid) and (not (display: inline-grid)) {
}

Note: There is no need to enclose the not operator between two parentheses at the top level. To combine it with other operators, like and and or, the parentheses are required.

The and operator

The and operator creates a new expression from the conjunction of two shorter expressions. It returns true only if both of the shorter expressions are also true. The following example returns true if and only if the two shorter expressions are simultaneously true:

css
@supports (display: table-cell) and (display: list-item) {
}

Multiple conjunctions can be juxtaposed without the need of more parentheses. The following are both equivalent:

css
@supports (display: table-cell) and (display: list-item) and (display: contents) {
}
@supports (display: table-cell) and
  ((display: list-item) and (display: contents)) {
}

The or operator

The or operator creates a new expression from the disjunction of two shorter expressions. It returns true if one or both of the shorter expressions is also true. The following example returns true if at least one of the two shorter expressions is true:

css
@supports (transform-style: preserve) or (-moz-transform-style: preserve) {
}

Multiple disjunctions can be juxtaposed without the need of more parentheses. The following are both equivalent:

css
@supports (transform-style: preserve) or (-moz-transform-style: preserve) or
  (-webkit-transform-style: preserve) {
}

@supports (transform-style: preserve-3d) or
  (
    (-moz-transform-style: preserve-3d) or
      (-webkit-transform-style: preserve-3d)
  ) {
}

Note: When using both and and or operators, the parentheses must be used to define the order in which they apply. Otherwise, the condition is invalid and the whole rule is ignored.

Formal syntax

@supports = 
@supports <supports-condition> { <rule-list> }

<supports-condition> =
not <supports-in-parens> |
<supports-in-parens> [ and <supports-in-parens> ]* |
<supports-in-parens> [ or <supports-in-parens> ]*

<supports-in-parens> =
( <supports-condition> ) |
<supports-feature> |
<general-enclosed>

<supports-feature> =
<supports-selector-fn> |
<supports-font-tech-fn> |
<supports-font-format-fn> |
<supports-at-rule-fn> |
<supports-named-feature-fn> |
<supports-env-fn> |
<supports-decl>

<general-enclosed> =
[ <function-token> <any-value>? ) ] |
[ ( <any-value>? ) ]

<supports-selector-fn> =
selector( <complex-selector> )

<supports-font-tech-fn> =
font-tech( <font-tech> )

<supports-font-format-fn> =
font-format( <font-format> )

<supports-at-rule-fn> =
at-rule( <at-keyword-token> )

<supports-named-feature-fn> =
named-feature( <ident> )

<supports-env-fn> =
env( <ident> )

<supports-decl> =
( [ <declaration> | <supports-condition-name> ] )

<complex-selector> =
<complex-selector-unit> [ <combinator>? <complex-selector-unit> ]*

<font-tech> =
<font-features-tech> |
<color-font-tech> |
variations |
palettes |
incremental

<font-format> =
<string> |
collection |
embedded-opentype |
opentype |
svg |
truetype |
woff |
woff2

<complex-selector-unit> =
[ <compound-selector>? <pseudo-compound-selector>* ]!

<combinator> =
'>' |
'+' |
'~' |
[ '|' '|' ] |
[ / <wq-name> / ]

<font-features-tech> =
features-opentype |
features-aat |
features-graphite

<color-font-tech> =
color-COLRv0 |
color-COLRv1 |
color-SVG |
color-sbix |
color-CBDT

<compound-selector> =
[ <type-selector>? <subclass-selector>* ]!

<pseudo-compound-selector> =
<pseudo-element-selector> <pseudo-class-selector>*

<wq-name> =
<ns-prefix>? <ident-token>

<type-selector> =
<wq-name> |
<ns-prefix>? '*'

<subclass-selector> =
<id-selector> |
<class-selector> |
<attribute-selector> |
<pseudo-class-selector>

<pseudo-element-selector> =
: <pseudo-class-selector> |
<legacy-pseudo-element-selector>

<pseudo-class-selector> =
: <ident-token> |
: <function-token> <any-value> )

<ns-prefix> =
[ <ident-token> | '*' ]? '|'

<id-selector> =
<hash-token>

<class-selector> =
'.' <ident-token>

<attribute-selector> =
'[' <wq-name> ']' |
'[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'

<legacy-pseudo-element-selector> =
: [ before | after | first-line | first-letter ]

<attr-matcher> =
[ '~' | '|' | '^' | '$' | '*' ]? '='

<attr-modifier> =
i |
s

Examples

Testing for the support of a CSS property

css
@supports (animation-name: test) {
  /* CSS applied when animations are supported without a prefix */
  @keyframes {
    /* Other at-rules can be nested inside */
  }
}

Testing for the support of a given CSS property or a prefixed version

css
@supports (text-stroke: 10px) or (-webkit-text-stroke: 10px) {
  /* CSS applied when text-stroke, prefixed or not, is supported */
}

Testing for the non-support of a specific CSS property

css
@supports not ((text-align-last: justify) or (-moz-text-align-last: justify)) {
  /* CSS to provide fallback alternative for text-align-last: justify */
}

Testing for the support of a selector

CSS conditional rules provide the ability to test for the support of a selector such as :has().

css
/* This rule won't be applied in browsers that don't support :has() */
ul:has(> li li) {
  /* CSS is applied when the :has(…) pseudo-class is supported */
}

@supports not selector(:has(a, b)) {
  /* Fallback for when :has() is unsupported */
  ul > li,
  ol > li {
    /* The above expanded for browsers that don't support :has(…) */
  }
}

/* Note: So far, there's no browser that supports the `of` argument of :nth-child(…) */
@supports selector(:nth-child(1n of a, b)) {
  /* This rule needs to be inside the @supports block, otherwise
     it will be partially applied in browsers which don't support
     the `of` argument of :nth-child(…) */
  :is(:nth-child(1n of ul, ol) a, details > summary) {
    /* CSS applied when the :is(…) selector and
       the `of` argument of :nth-child(…) are both supported */
  }
}

Testing for the support of a font technology

The following example applies the Bungee Spice color font if the browser supports the COLRv1 font technology:

css
@supports font-tech(color-COLRv1) {
  body {
    font-family: "Bungee Spice", fantasy;
  }
}

It's also possible to test for the support of a font technology by using the tech function inside the @font-face at-rule. In the following example, if a browser doesn't support the color font technology in the bungee-spice.woff2 font, a regular bungee.woff2 font will be used instead.

css
@font-face {
  font-family: "Bungee Spice";
  src:
    url("bungee-spice.woff2") tech(color-COLRv1) format("woff2"),
    url("bungee.woff2") format("woff2");
}

Testing for the support of a font format

The following example uses the WOFF2 version of the font if the browser supports this font format, otherwise it falls back to the previously specified WOFF version:

css
@font-face {
  font-family: "Open Sans WOFF";
  src: url("open-sans.woff") format("woff");
}

@font-face {
  font-family: "Open Sans WOFF2";
  src: url("open-sans.woff2") format("woff2");
}

body {
  font-family: "Open Sans WOFF", sans-serif;
}

@supports font-format(woff2) {
  body {
    font-family: "Open Sans WOFF2", sans-serif;
  }
}

However, a more efficient way to specify multiple font formats is to list them in the src descriptor of a single @font-face at-rule in the order from the most preferred format to the least preferred:

css
@font-face {
  font-family: "Open Sans";
  src:
    url("open-sans.woff2") format("woff2"),
    url("open-sans.woff") format("woff");
}

body {
  font-family: "Open Sans", sans-serif;
}

Specifications

Specification
CSS Conditional Rules Module Level 5
# at-supports-ext
CSS Conditional Rules Module Level 4
# at-supports-ext
CSS Conditional Rules Module Level 3
# at-supports

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
@supports
Chrome – Full support
Chrome 28 (Release date: 2013-07-09)
footnote Full support
Edge – Full support
Edge 12 (Release date: 2015-07-29)
footnote Full support
Firefox – Full support
Firefox 22 (Release date: 2013-06-25)
footnote Full support
Opera – Full support
Opera 12.1 (Release date: 2012-11-20)
footnote Full support
Safari – Full support
Safari 9 (Release date: 2015-09-30)
footnote Full support
Chrome Android – Full support
Chrome Android 28 (Release date: 2013-07-10)
footnote Full support
Firefox for Android – Full support
Firefox for Android 22 (Release date: 2013-06-25)
footnote Full support
Opera Android – Full support
Opera Android 12.1 (Release date: 2012-10-09)
footnote Full support
Safari on iOS – Full support
Safari on iOS 9 (Release date: 2015-09-16)
footnote Full support
Samsung Internet – Full support
Samsung Internet 1.5 (Release date: 2013-09-25)
footnote Full support
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
footnote Full support
WebView on iOS – Full support
WebView on iOS 9 (Release date: 2015-09-16)
footnote Full support
font-format()
Chrome – Full support
Chrome 108 (Release date: 2022-11-29)
footnote Full support
Edge – Full support
Edge 108 (Release date: 2022-12-05)
footnote Full support
Firefox – Full support
Firefox 106 (Release date: 2022-10-18)
footnote Full support
Opera – Full support
Opera 94 (Release date: 2022-12-15)
footnote Full support
Safari – Full support
Safari 17 (Release date: 2023-09-18)
footnote Full support
Chrome Android – Full support
Chrome Android 108 (Release date: 2022-11-29)
footnote Full support
Firefox for Android – Full support
Firefox for Android 106 (Release date: 2022-10-18)
footnote Full support
Opera Android – Full support
Opera Android 73 (Release date: 2023-01-17)
footnote Full support
Safari on iOS – Full support
Safari on iOS 17 (Release date: 2023-09-18)
footnote Full support
Samsung Internet – Full support
Samsung Internet 21 (Release date: 2023-05-19)
footnote Full support
WebView Android – Full support
WebView Android 108 (Release date: 2022-11-29)
footnote Full support
WebView on iOS – Full support
WebView on iOS 17 (Release date: 2023-09-18)
footnote Full support
font-tech()
Chrome – Full support
Chrome 108 (Release date: 2022-11-29)
footnote Full support
Edge – Full support
Edge 108 (Release date: 2022-12-05)
footnote Full support
Firefox – Full support
Firefox 106 (Release date: 2022-10-18)
footnote Full support
Opera – Full support
Opera 94 (Release date: 2022-12-15)
footnote Full support
Safari – Full support
Safari 17 (Release date: 2023-09-18)
footnote Full support
Chrome Android – Full support
Chrome Android 108 (Release date: 2022-11-29)
footnote Full support
Firefox for Android – Full support
Firefox for Android 106 (Release date: 2022-10-18)
footnote Full support
Opera Android – Full support
Opera Android 73 (Release date: 2023-01-17)
footnote Full support
Safari on iOS – Full support
Safari on iOS 17 (Release date: 2023-09-18)
footnote Full support
Samsung Internet – Full support
Samsung Internet 21 (Release date: 2023-05-19)
footnote Full support
WebView Android – Full support
WebView Android 108 (Release date: 2022-11-29)
footnote Full support
WebView on iOS – Full support
WebView on iOS 17 (Release date: 2023-09-18)
footnote Full support
selector()
Chrome – Full support
Chrome 83 (Release date: 2020-05-19)
footnote Full support
Edge – Full support
Edge 83 (Release date: 2020-05-21)
footnote Full support
Firefox – Full support
Firefox 69 (Release date: 2019-09-03)
footnote Full support
Opera – Full support
Opera 69 (Release date: 2020-06-24)
footnote Full support
Safari – Full support
Safari 14.1 (Release date: 2021-04-26)
footnote Full support
Chrome Android – Full support
Chrome Android 83 (Release date: 2020-05-19)
footnote Full support
Firefox for Android – Full support
Firefox for Android 79 (Release date: 2020-07-28)
footnote Full support
Opera Android – No support
Opera Android
footnote
footnote See bug 40633900
Safari on iOS – Full support
Safari on iOS 14.5 (Release date: 2021-04-26)
footnote Full support
Samsung Internet – Full support
Samsung Internet 13 (Release date: 2020-12-02)
footnote Full support
WebView Android – Full support
WebView Android 83 (Release date: 2020-05-19)
footnote Full support
WebView on iOS – Full support
WebView on iOS 14.5 (Release date: 2021-04-26)
footnote Full support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
No support
No support
See implementation notes.

See also