アットルール サポートに基づいて CSS を条件付きで適用する

ウェブ機能: at-rule()

@supports at-rule(@<at-rule name>) {…} を使用すると、特定の at-rule がブラウザでサポートされている場合にのみ、特定の CSS ルールまたは宣言を条件付きで適用できます。これには、ルール全体を含めることも、CSS のネストと組み合わせて特定の宣言を条件付きで適用することもできます。

.foo {
  background: var(--accent-color);

  @supports at-rule(@property) {
    background-image: var(--rainbow-gradient);
    animation: sliding-rainbow 1s linear infinite;
  }
}

検出された at-rule のみを条件付きで適用するために @supports at-rule() を使用しないでください。

/* 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-rule() を使用できない場合は、以下のガイダンスを使用できます。

プロパティ、値、セレクタを最初に試す

@supports は、プロパティ、値、セレクタを(@supports selector(...) を介して)すでに検出できます。多くの場合、これらを使用して、アットルール自体を確認することなく、機能のサポートを検出できます。

たとえば、カスタム関数のサポートを検出するために @supports at-rule(@function) を使用する代わりに、@supports (color: --foo()) を使用できます。

また、特定の at-rule がサポートされている場合にのみ使用できる疑似クラスや疑似要素があり、これらを使用してサポートを検出できる場合もあります。

コンテナクエリのタイプを検出する

at-rule() では、名前による at-rule の検出のみが可能です。他の構文や記述子の検出はできません。たとえば、次の場合は機能しません。

@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, );
}

より汎用的なソリューションとして、継承されないプロパティを登録し、ルート要素で (スペース)に設定することもできます。

{# テストケース: 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 を使用する

アットルール全体については、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 構造から特定のタイプのコンテナクエリのサポートを検出する方法はありません。
  • @property のサポートは少し広いため、@property のサポートを検出するために CSS.registerProperty を使用しないでください。

代替戦略

これがサポート対象内である場合を除き、@supports (at-rule()) 機能自体よりもサポート範囲が狭いアットルールを検出するには、@supports (at-rule()) のみを使用してください。

この機能より前にリリースされた at-rule のサポートに基づいて CSS を条件付きで適用するには、上記のセクションのガイダンスを使用します。

@supports at-rule() 機能自体のサポートを検出するには、@supports at-rule() をサポートするすべてのブラウザに存在することが保証されている at-rule(@supports at-rule(@media) { ... } など)を使用します。