セマンティック コンポーネントの適応

スタイルクエリ(@container style())を使用すると、各コンテキストを生成または反応するものをハードコードすることなく、コンテキストのバリエーションをトリガーできます。これにより、デザイン システムの結合が軽減され、拡張性とコンポーネントのカプセル化が向上します。

たとえば、section.featured { --surface: featured } ルールでコンテキストをマークし、ランディング ページでも main { --surface: featured } を介してデフォルトでそのコンテキストをマークできます。コンポーネントは --surface: featured に反応するようにオプトインします。たとえば、カードにプロモーション バッジが表示されたり、ボタンがデフォルトで塗りつぶしバリアントになったりします。

スタイルクエリを使用すると、両側を分離したままにできます。注目のサーフェスは、適応する要素に名前を付けることはなく、コンポーネントはコンテキストを生成したものを検査しません。どちらの側も、もう一方に触れることなく、新しいコンポーネントや新しい機能サーフェスを独立して拡張できます。子孫セレクタ(.featured .button など)は、これとは逆の動作を強制します。セレクタは関係の両側をエンコードする必要があり、どちらかが変更されるたびに変更する必要があります。

このガイドを使用するタイミング

このガイドでは、動作の変更について説明します。コンポーネントは、コンテキストに応じて、レンダリングする内容、配置方法、表示するバリアントを決定します。たとえば、バッジの表示 / 非表示、レイアウト方向の切り替え、ボタン バリアントの入れ替えなどです。

代わりに、トークンレベルの変更(密度モード、テーマ、または多くのコンポーネントにわたってパディングや色などの値を均一にシフトするその他の高次トークン)が必要な場合は、デザイン トークンの反応性をご覧ください。

適切なツールの選択

コンテキスト関係の両側が独立して変化する可能性がある場合、つまり、新しい要素がコンテキストを生成し始めるか、新しいコンポーネントがコンテキストに反応し始める可能性がある場合は、スタイルクエリを使用します。この間接的な指定は、拡張性とカプセル化の点でメリットがあります。また、スタイルクエリは、子孫セレクタでは不可能な Shadow DOM の境界を越えることができます。この柔軟性が必要ない場合は、よりシンプルなツールを使用することをおすすめします。

  • 子孫セレクタ(.toolbar .button): 再利用や拡張ができない、固定された 1 回限りの関係。YAGNI が適用されます。使用しない間接参照は追加しないでください。
  • サイズクエリ(@container (min-width: …)): セマンティックな状態ではなく、利用可能なスペースによってレイアウトと密度が変化します。
  • スタイルクエリ(@container style(…)): セマンティック状態。特定のコンテキストでコンポーネントがレンダリング、配置、表示する内容。

実装ディレクティブ

  1. コンテナの CSS カスタム プロパティを使用して、セマンティック コンテキスト フラグを定義します。
  2. スタイルクエリに container-type を設定しないでください。スタイルクエリは、最も近い祖先の継承されたカスタム プロパティをクエリするため、明示的なコンテインメント コンテキストは必要ありません。
  3. 必須: @container style(--property: value) を使用して、子孫要素に条件付きスタイルを適用します。スタイルクエリは、プロパティが設定されている要素ではなく、その子孫のみに一致します。
  4. 推奨: 関係を拡張可能にする必要がある場合や、コンポーネント / シャドウ DOM の境界を越える必要がある場合は、子孫セレクタよりもスタイルクエリを優先します(上記の適切なツールの選択を参照)。ただし、間接参照が何ももたらさない固定の 1 回限りの関係には、子孫セレクタを使用します。

実装例

/* 1. Set the context on a layout container */
.featured {
  --surface: featured; /* Semantic context flag for children */
}

/* 2. Component reacts to inherited flag */
.button {
  /* Default: Outlined informational style */
  background: transparent;
  border: 1px solid currentColor;
}

.badge {
  /* Default: Hidden — only revealed in featured surfaces */
  display: none;
}

@container style(--surface: featured) {
  .button {
    /* Automatic switch to Filled promotional style */
    background: var(--brand-accent);
    color: white;
    border: none;
  }

  .badge {
    /* Reveal decorative elements only in featured context */
    display: block;
  }
}

代替戦略

コンテナ スタイルクエリが広く利用可能になるまでは、プログレッシブ エンハンスメントとしてレイヤ化します。つまり、どこでも機能するセレクタベースのデフォルトをリリースし、サポートされている場合はスタイルクエリでオーバーライドできるようにします。コンテキスト セレクタで :where() を使用すると、スタイルクエリ(同じ詳細度、ソース順序で後)が自動的に優先されます。

/* Default styles — work everywhere */
.button {
  background: transparent;
  border: 1px solid currentColor;
}

.badge {
  display: none;
}

/* Selector-based contextual styles — broad browser support */
:where(.featured) .button {
  background: var(--brand-accent);
  color: white;
  border: none;
}

:where(.featured) .badge {
  display: block;
}

/* Progressive enhancement: style queries override when supported */
@container style(--surface: featured) {
  .button {
    background: var(--brand-accent);
    color: white;
    border: none;
  }

  .badge {
    display: block;
  }
}

セレクタ フォールバックは、コンテキスト スタイルをクラス名に関連付けます。これにより、コンポーネントが DOM の配置に結合されます。スタイルクエリが広くサポートされるようになると、:where() ルールを削除できます。