@supports

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 2015 年 9 月以来,该特性已在各大浏览器中可用。

* 此特性的某些部分可能存在不同级别的支持。

@supports CSS @ 规则可用于指定一组依赖于浏览器对 CSS 功能支持情况的 CSS 声明。这种用法通常被称为特性查询(feature query)。该规则必须置于代码的顶层,或嵌套在任何其他条件组 @ 规则内。

试一试

.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>

在 JavaScript 中,可以通过 CSS 对象模型接口 CSSSupportsRule 来访问 @supports

语法

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. */
}

@supports @ 规则由一个带有支持条件的语句块组成。这些条件可以通过合取(and)、析取(or)和/或否定(not)进行组合。操作符的优先级可以通过括号来定义。

支持条件可以使用 <property>: <value> 声明语法或 <function()> 函数语法。以下各节描述了每种支持条件的用法。

声明语法

声明语法用于检查浏览器是否支持指定的 <property>: <value> 声明。该声明必须用括号括起来。如果浏览器支持 transform-origin: 5% 5% 表达式,以下示例将返回 true。

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

函数语法

函数语法用于检查浏览器是否支持函数内的值或表达式。函数语法支持的函数将在以下各节中描述。

selector()

此函数评估浏览器是否支持指定的选择器语法。如果浏览器支持子代组合器,以下示例将返回 true 并应用 CSS 样式。

css
@supports selector(h2 > p) {
}

font-tech()

此函数检查浏览器是否支持指定的字体技术进行布局和渲染。如果浏览器支持 COLRv1 字体技术,以下示例将返回 true 并应用 CSS 样式。

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

下表描述了可以使用 font-tech() 函数查询的字体技术(<font-tech>),包括彩色字体技术(<color-font-tech>)、字体特性技术(<font-features-tech>)以及其他可用的字体技术。

技术 支持
<color-font-tech>
color-colrv0 通过 COLR 版本 0 表实现的多色字形
color-colrv1 通过 COLR 版本 1 表实现的多色字形
color-svg SVG 多色表
color-sbix 标准位图图形表
color-cbdt 彩色位图数据表
<font-features-tech>
features-opentype OpenType GSUBGPOS
features-aat TrueType morxkerx
features-graphite Graphite 特性,即 SilfGlatGlocFeatSill
其他 <font-tech>
incremental-patch 使用 patch 子集方法进行增量字体加载
incremental-range 使用范围请求方法进行增量字体加载
incremental-auto 使用方法协商进行增量字体加载
variations TrueType 和 OpenType 字体中的字体变体,用于控制字体轴、字重、字形等。
palettes 通过 font-palette 实现的字体调色板,用于在字体中选择多个调色板之一

font-format()

此函数检查浏览器是否支持指定的字体格式进行布局和渲染。如果浏览器支持 opentype 字体格式,以下示例将返回 true 并应用 CSS 样式。

css
@supports font-format(opentype) {
}

下表描述了可使用此函数查询的可用格式(<font-format> 值)。

格式 描述 文件扩展名
collection OpenType 集合 .otc, .ttc
embedded-opentype 嵌入式 OpenType .eot
opentype OpenType .ttf, .otf
svg SVG 字体(已弃用) .svg, .svgz
truetype TrueType .ttf
woff WOFF 1.0(Web 开放字体格式) .woff
woff2 WOFF 2.0(Web 开放字体格式) .woff2

not 操作符

not 操作符位于表达式之前,表示对表达式的否定。如果浏览器的 transform-origin 属性认为 10em 10em 10em 无效,则以下表达式返回 true:

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

与任何操作符一样,not 操作符可以应用于任何复杂度的声明。以下两个示例都是有效的。

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

备注: 在顶层,不需要用括号将 not 操作符括起来。但要将其与 andor 等其他操作符组合使用时,则必须使用括号。

and 操作符

and 操作符通过两个较短表达式的合取来创建一个新表达式。它仅当两个较短表达式都为 true 时才返回 true。以下示例当且仅当两个较短表达式同时为 true 时才返回 true。

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

多个合取可以并列,而无需更多括号。以下两者是等效的。

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

or 操作符

or 操作符通过两个较短表达式的析取来创建一个新表达式。如果一个或两个较短表达式为 true,它就返回 true。以下示例在至少有一个较短表达式为 true 时返回 true。

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

多个析取可以并列,而无需更多括号。以下两者是等效的。

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)
  ) {
}

备注: 当同时使用 andor 操作符时,必须使用括号来定义它们的应用顺序。否则,条件将无效,整个规则将被忽略。

正式语法

@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-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-decl> =
( <declaration> )

<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> =
'>' |
'+' |
'~' |
[ '|' '|' ]

<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>*

<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> )

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

<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

示例

测试对 CSS 属性的支持

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

测试对给定 CSS 属性或其带前缀版本的支持

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

测试对特定 CSS 属性的不支持

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

测试对选择器的支持

CSS 条件规则提供了测试对选择器(例如 :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 */
  }
}

测试对字体技术的支持

如果浏览器支持 COLRv1 字体技术,以下示例将应用 CSS 样式。

css
@import "https://fonts.googleapis.ac.cn/css2?family=Bungee+Spice";

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

也可以通过在 @font-face @ 规则中使用 tech 函数来测试对字体技术的支持。如果浏览器不支持该字体技术,则可以使用备用字体(Bungee-fallback.otf)。

css
@font-face {
  font-family: "Bungee Spice";
  src:
    url("https://fonts.googleapis.ac.cn/css2?family=Bungee+Spice")
      tech(color-COLRv1),
    url("Bungee-fallback.otf") format("opentype");
}

测试对字体格式的支持

如果浏览器支持 woff2 字体格式,以下示例将应用 CSS 样式。

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

规范

规范
CSS 条件规则模块第 4 级
# at-supports-ext
CSS 条件规则模块第 3 级
# at-supports

浏览器兼容性

另见