根据 at 规则支持情况有条件地应用 CSS

Web 功能: at-rule()

使用 @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) { ... }。