使用 @supports at-rule(@<at-rule name>) {…},仅在浏览器支持特定 at 规则时,才会有条件地应用特定 CSS 规则或声明。
这可以包含整个规则,也可以与 CSS 嵌套结合使用,以有条件地应用某些声明。
.foo {
background: var(--accent-color);
@supports at-rule(@property) {
background-image: var(--rainbow-gradient);
animation: sliding-rainbow 1s linear infinite;
}
}
请勿使用 @supports at-rule() 有条件地应用正在检测的 at 规则,而不应用其他任何规则。
/* BAD: CSS already ignores rules the browser doesn't understand, so this is unnecessary */
@supports at-rule(@starting-style) {
@starting-style {
/* ... */
}
}
在 @supports at-rule() 不合适时检测对 at 规则的支持
如果由于浏览器支持问题或需要更深入的检测而无法使用 at-rule(),您可以使用以下指南。
先尝试属性、值或选择器
@supports 已经可以检测属性、值和选择器(通过 @supports selector(...))。在许多情况下,您可以使用这些来检测对功能的支持,而无需检查 at 规则本身。
例如,您可以使用 @supports (color: --foo()),而不是 @supports at-rule(@function) 来检测对自定义函数的支持。
在其他情况下,可能存在仅在支持特定 at 规则时才可用的伪类或伪元素,这些伪类或伪元素可用于检测支持情况。
检测容器查询类型
at-rule() 仅允许按名称检测 at 规则。它不允许检测其他语法或描述符。
例如,以下方法不起作用:
@supports at-rule(@container style(--a: 1)) {
/* ... */
}
对于许多类型的容器查询,您可以使用 container-type 并设置合适的值。例如,@supports (container-type: scroll-state) 用于滚动状态查询,或 @supports (container-type: size)container-type: anchoredforanchored()` 查询。
不过,样式查询没有 container-type。
重要提示:请勿尝试使用 @supports (container-type: style) 来检测对样式查询的支持,因为这不起作用。
您可以尝试使用始终为 true 的样式查询:
@container style(--a: 1) or (not (style(--a: 1))) {
/* Rules here will only be applied if style queries are supported */
}
只要属性名称和值在两者中相同,无论您使用什么属性名称或值,这都会在支持样式查询的任何浏览器中匹配。
已注册的自定义属性 (@property)
在某些情况下,如果要应用的条件 CSS 可以缩减为单个属性,您可以使用为此目的注册的专用自定义属性:
/* Use a custom property to conditionally include the dash animation */
@property --progress-dash-animation {
syntax: "*";
inherits: false;
initial-value: , progress-dash 3s ease-in-out infinite;
}
.spinner {
/* The dash animation is only included if @property is supported */
animation:
progress-spin var(--_used-spinner-duration) linear infinite
var(--progress-dash-animation, );
}
如需更通用的解决方案,您可以注册一个非继承属性,并在根元素上将其设置为 (空格):
{# Testcase: https://codepen.io/leaverou/pen/KwWzpVr #}
@property --supports-atproperty {
syntax: "*";
inherits: false;
}
:root {
--supports-atproperty: ;
}
body {
/* The background is only applied if @property is supported */
background: var(--supports-atproperty, green);
}
注意:
- 只有在空格是可接受的替代字符时,这两种方法才有效。对于其他情况,您需要使用 JS,如下所述。
- 通用解决方案依赖于非继承,因此不适用于根元素上的声明。
万不得已时使用 JavaScript
对于整个 at 规则,请检查 JavaScript 中是否存在某些接口。
例如,如果定义了 globalThis.CSSFunctionRule,则支持 @function。
如果您需要进行更深入的测试(例如,针对某些前奏、嵌套规则、描述符),可以设置测试并检查其解析方式:
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
@page {
@top-left {
content: "test";
}
}
`);
const SUPPORTS_PAGE_MARGINS = Boolean(sheet.cssRules[0]?.cssRules?.[0]);
重要提示:
- 使用 JS 检测对 CSS 功能的支持时,请勿直接通过 JS 应用样式。而是应该将类应用于根元素,并在 CSS 中进行分支。
- 请注意,即使前导部分无法识别,容器查询也会被解析,并且无法从 CSSOM 结构中检测对某些类型容器查询的支持。
- 请勿使用
CSS.registerProperty检测对@property的支持,因为其支持范围略广。
后备策略
除非这在您的支持目标范围内,否则仅使用 @supports (at-rule()) 来检测支持范围比 @supports (at-rule()) 功能本身更窄的 at 规则。
如需根据对此功能发布之前提供的 at 规则的支持情况有条件地应用 CSS,请使用上一部分中的指南。
如需检测对 @supports at-rule() 功能本身的支持,您可以使用保证在所有支持 @supports at-rule() 的浏览器中都存在的 at 规则,例如 @supports at-rule(@media) { ... }。