根據 At 規則支援,有條件地套用 CSS

網頁功能: 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) { ... }。