mozilla

Revision 357003 of @supports

  • Revision slug: CSS/@supports
  • Revision title: @supports
  • Revision id: 357003
  • Created:
  • Creator: FredB
  • Is current revision? No
  • Comment

Revision Content

{{ CSSRef() }}

{{ SeeCompatTable() }}

Summary

The @supports CSS at-rule associates a set of nested statements, in a CSS block, that is delimited by curly braces, with a condition consisting of testing of CSS declarations, that is property-value pairs, combined with arbitrary conjunctions, disjunctions, and negations of them. Such a condition is called a supports condition.

It allows to perform a feature query.

The @supports at-rule may be used not only at the top level of a CSS, but also inside any CSS conditional-group at-rule and can be accessed via the CSS object model interface {{domxref("CSSSupportsRule")}}.

Syntax

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

A supports condition consists of one or several declarations combined by different logical operators. Precedence of operators can be overruled by using parenthesis.

Declaration syntax

The simplest expression is a CSS declaration, that is a CSS property name followed by a value, separated by a colon. The following expression

( transform-origin: 5% 5% )

returns true if the {{ cssxref("transform-origin") }} implements a syntax considering 5% 5% as valid.

A CSS declaration is always included into parenthesis.

The not operator

The not operator can precede any expression to create a new expression, resulting in the negation of the original expression. The following expression

not ( transform-origin: 10em 10em 10em )

returns true if {{ cssxref("transform-origin") }} doesn't implement a syntax considering 10em 10em 10em as valid.

Like any operator, the not operator can be applying to a declaration of any complexity. The following examples are all valid expressions:

not ( not ( transform-origin: 2px ) )
(display: flexbox) and ( not (display: inline-grid) )

Note: there is no need to enclose the not operator between two parenthesis when at the top level. But to combine it with other operators, like and and or, the parenthesis are required.

The and operator

From two expressions, the and operator creates a new expression consisting in the conjunction of the two original ones, that is the resulting expression is true only if both of the original expressions also resolve to true. In this example, the complete expression resolves to true if and only if the two expressions are simultaneously true:

(display: table-cell) and (display: list-item)

Several conjunctions can be juxtaposed without the need of more parenthesis:

(display: table-cell) and (display: list-item) and (display:run-in)

is equivalent to:

(display: table-cell) and ((display: list-item) and (display:run-in))

The or operator

From two expressions, the or operator creates a new expression consisting in the disjunction of the two original ones, that is the resulting expression is true if one, or both, of the original expressions also resolves to true. In this example, the complete expression resolves to true if at least one of the two expressions is true:

( transform-style: preserve ) or ( -moz-transform-style: preserve )

Several disjunctions can be juxtaposed without the need of more parenthesis:

( transform-style: preserve ) or ( -moz-transform-style: preserve ) or 
( -o-transform-style: preserve ) or ( -webkit-transform-style: preserve  )

is equivalent to:

( transform-style: preserve-3d ) or (( -moz-transform-style: preserve-3d ) or 
(( -o-transform-style: preserve-3d ) or ( -webkit-transform-style: preserve-3d  )))

Note: when using both and and or operators, the parenthesis must be used in order to define the order in which they apply. If not, the condition is invalid leading to the whole at-rule to be ignored.

Examples

Testing for the support of a specific CSS property

@supports (animation-name: test) {
    … /* specific CSS applied when animations are supported unprefixed */
    @keyframes { /* @supports being a CSS conditional group at-rule, it can includes other relevent at-rules */
      …
    }
}

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

@supports ( (perspective: 10px) or (-moz-perspective: 10px) or (-webkit-perspective: 10px) or
            (-ms-perspective: 10px) or (-o-perspective: 10px) ) {
    … /* specific CSS applied when 3D transforms, eventually prefixed, are supported */
}

Testing for the non-support of a specific CSS property

@supports ( not ((text-align-last:justify) or (-moz-text-align-last:justify) ){
    … /* specific CSS applied to simulate text-align-last:justify */
}

Specifications

Specification Status Comment
{{ SpecName('CSS3 Conditional', '#at-supports', '@supports') }} {{ Spec2('CSS3 Conditional') }}  

Browser compatibility

{{ CompatibilityTable() }}

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support {{ CompatNo() }} {{ CompatGeckoDesktop("17") }}[*] {{ CompatNo() }} 12.1 {{ CompatNo() }}
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support {{ CompatNo() }} {{ CompatGeckoMobile("17") }}[*] {{ CompatNo() }} 12.1 {{ CompatNo() }}

[*] As prefixing this at-rule has no sense, the @supports at-rule is only supported if the user enables it by setting the config value layout.css.supports-rule.enabled to true.

See also

  • {{ CSS_at_rules() }}
  • The CSSOM class {{ domxref("CSSSupportsRule") }}, and the {{ domxref("window.supportCSS") }} method that allows to perform the same check via JavaScript.

Revision Source

<p>{{ CSSRef() }}</p>
<p>{{ SeeCompatTable() }}</p>
<h2 id="Summary">Summary</h2>
<p>The <code>@supports</code> <a href="/en/CSS" title="CSS">CSS</a> <a href="/en/CSS/At-rule" title="en/CSS/At-rule">at-rule</a> associates a set of nested statements, in a CSS block, that is delimited by curly braces, with a condition consisting of testing of CSS declarations, that is property-value pairs, combined with arbitrary conjunctions, disjunctions, and negations of them. Such a condition is called a <em>supports condition</em>.</p>
<p>It allows to perform a <em>feature query</em>.</p>
<p>The <code>@supports</code> at-rule may be used not only at the top level of a CSS, but also inside any <a href="/en/CSS/At-rule#Conditional_Group_Rules" title="en/CSS/At-rule#Conditional_Group_Rules">CSS conditional-group at-rule</a> and can be accessed via the CSS object model interface {{domxref("CSSSupportsRule")}}.</p>
<h2 id="Syntax" name="Syntax">Syntax</h2>
<pre class="syntaxbox">
@supports <em>&lt;supports_condition&gt;</em> {
  /* specific rules */
}
</pre>
<p>A supports condition consists of one or several declarations combined by different logical operators. Precedence of operators can be overruled by using parenthesis.</p>
<h3 id="Declaration_syntax">Declaration syntax</h3>
<p>The simplest expression is a CSS declaration, that is a CSS property name followed by a value, separated by a colon. The following expression</p>
<pre class="brush:css">
( transform-origin: 5% 5% )</pre>
<p>returns true if the {{ cssxref("transform-origin") }} implements a syntax considering <code>5% 5%</code> as valid.</p>
<p>A CSS declaration is always included into parenthesis.</p>
<h3 id="The_not_operator">The <code>not</code> operator</h3>
<p>The <code>not</code> operator can precede any expression to create a new expression, resulting in the negation of the original expression. The following expression</p>
<pre class="brush:css">
not ( transform-origin: 10em 10em 10em )</pre>
<p>returns true if {{ cssxref("transform-origin") }} doesn't implement a syntax considering <code>10em 10em 10em</code> as valid.</p>
<p>Like any operator, the <code>not</code> operator can be applying to a declaration of any complexity. The following examples are all valid expressions:</p>
<pre class="brush:css">
not ( not ( transform-origin: 2px ) )
(display: flexbox) and ( not (display: inline-grid) )</pre>
<div class="note style-wrap">
  <p><strong>Note:</strong> there is no need to enclose the <code>not</code> operator between two parenthesis when at the top level. But to combine it with other operators, like <code>and</code> and <code>or</code>, the parenthesis are required.</p>
</div>
<h3 id="The_and_operator">The <code>and</code> operator</h3>
<p>From two expressions, the <code>and</code> operator creates a new expression consisting in the conjunction of the two original ones, that is the resulting expression is true only if both of the original expressions also resolve to true. In this example, the complete expression resolves to true if and only if the two expressions are simultaneously true:</p>
<pre class="brush:css">
(display: table-cell) and (display: list-item)</pre>
<p>Several conjunctions can be juxtaposed without the need of more parenthesis:</p>
<pre class="brush:css">
(display: table-cell) and (display: list-item) and (display:run-in)</pre>
<p>is equivalent to:</p>
<pre class="brush:css">
(display: table-cell) and ((display: list-item) and (display:run-in))</pre>
<h3 id="The_or_operator">The <code>or</code> operator</h3>
<p>From two expressions, the <code>or</code> operator creates a new expression consisting in the disjunction of the two original ones, that is the resulting expression is true if one, or both, of the original expressions also resolves to true. In this example, the complete expression resolves to true if at least one of the two expressions is true:</p>
<pre class="brush:css;">
( transform-style: preserve ) or ( -moz-transform-style: preserve )</pre>
<p>Several disjunctions can be juxtaposed without the need of more parenthesis:</p>
<pre class="brush:css">
( transform-style: preserve ) or ( -moz-transform-style: preserve ) or 
( -o-transform-style: preserve ) or ( -webkit-transform-style: preserve  )</pre>
<p>is equivalent to:</p>
<pre class="brush:css">
( transform-style: preserve-3d ) or (( -moz-transform-style: preserve-3d ) or 
(( -o-transform-style: preserve-3d ) or ( -webkit-transform-style: preserve-3d  )))</pre>
<div class="note style-wrap">
  <p><strong>Note</strong>: when using both <code>and</code> and <code>or</code> operators, the parenthesis must be used in order to define the order in which they apply. If not, the condition is invalid leading to the whole at-rule to be ignored.</p>
</div>
<h2 id="Examples">Examples</h2>
<h3 id="Testing_for_the_support_of_a_specific_CSS_property">Testing for the support of a specific CSS property</h3>
<pre class="brush:css;">
@supports (animation-name: test) {
    … /* specific CSS applied when animations are supported unprefixed */
    @keyframes { /* @supports being a CSS conditional group at-rule, it can includes other relevent at-rules */
      …
    }
}
</pre>
<h3 id="Testing_for_the_support_of_a_specific_CSS_property_or_a_prefixed_version">Testing for the support of a specific CSS property or a prefixed version</h3>
<pre class="brush:css;">
@supports ( (perspective: 10px) or (-moz-perspective: 10px) or (-webkit-perspective: 10px) or
            (-ms-perspective: 10px) or (-o-perspective: 10px) ) {
    … /* specific CSS applied when 3D transforms, eventually prefixed, are supported */
}
</pre>
<h3 id="Testing_for_the_non-support_of_a_specifc_CSS_property">Testing for the non-support of a specific CSS property</h3>
<pre class="brush:css;">
@supports ( not ((text-align-last:justify) or (-moz-text-align-last:justify) ){
    … /* specific CSS applied to simulate text-align-last:justify */
}</pre>
<h2 id="Specifications">Specifications</h2>
<table class="standard-table">
  <thead>
    <tr>
      <th scope="col">Specification</th>
      <th scope="col">Status</th>
      <th scope="col">Comment</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>{{ SpecName('CSS3 Conditional', '#at-supports', '@supports') }}</td>
      <td>{{ Spec2('CSS3 Conditional') }}</td>
      <td>&nbsp;</td>
    </tr>
  </tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">Browser compatibility</h2>
<p>{{ CompatibilityTable() }}</p>
<div id="compat-desktop">
  <table class="compat-table">
    <tbody>
      <tr>
        <th>Feature</th>
        <th>Chrome</th>
        <th>Firefox (Gecko)</th>
        <th>Internet Explorer</th>
        <th>Opera</th>
        <th>Safari</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatGeckoDesktop("17") }}[*]</td>
        <td>{{ CompatNo() }}</td>
        <td>12.1</td>
        <td>{{ CompatNo() }}</td>
      </tr>
    </tbody>
  </table>
</div>
<div id="compat-mobile">
  <table class="compat-table">
    <tbody>
      <tr>
        <th>Feature</th>
        <th>Android</th>
        <th>Firefox Mobile (Gecko)</th>
        <th>IE Mobile</th>
        <th>Opera Mobile</th>
        <th>Safari Mobile</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatGeckoMobile("17") }}[*]</td>
        <td>{{ CompatNo() }}</td>
        <td>12.1</td>
        <td>{{ CompatNo() }}</td>
      </tr>
    </tbody>
  </table>
</div>
<p>[*] As prefixing this at-rule has no sense, the <code>@supports</code> at-rule is only supported if the user enables it by setting the config value <code>layout.css.supports-rule.enabled</code> to true.</p>
<h2 id="See_also">See also</h2>
<ul>
  <li>{{ CSS_at_rules() }}</li>
  <li>The CSSOM class {{ domxref("CSSSupportsRule") }}, and the {{ domxref("window.supportCSS") }} method that allows to perform the same check via JavaScript.</li>
</ul>
Revert to this revision