Understanding new CSS at-rule @scope
記事は上記記事を意訳したものです。
※当ブログでの翻訳記事は元サイト様に許可を得て掲載しています。
テンプレートを作成する際、開発者は特異性と柔軟性のバランスを取るのに苦労することがよくあります。一方では、選択する要素について具体的であることを目指し、他方では、セレクタが簡単にオーバーライドでき、DOM構造に密接に結びついていないことが望まれます。
時間とともに、開発者はさまざまな解決策や回避策を編み出し、発見してきました。例えば:
- 特定のライブラリは、セレクタを完全に排除し、スタイリングのトリガーを直接マークアップに埋め込むことを要求します。
- SMACSS、BEMなどのCSSメソドロジーを使用することで、明確で一貫した命名構造を作成し、コードの異なる部分の関係を理解しやすくし、大規模プロジェクトの保守を容易にします。
- Scoped CSSやStyled ComponentsなどのJavaScriptベースのソリューションは、ランダムに生成された文字列(例:sc-596d7e0e-4)を付加してセレクタを書き換え、ページの他の場所で意図しない要素のターゲティングを防ぎます。
しかし、これらのどれも必要ないとしたらどうでしょうか?CSSが、高い特異性やDOMとの密接な結合を必要とせずに、選択された要素について具体的になる方法を提供しているとしたらどうでしょうか?
はい。新しく導入されたCSS at-rule @scopeが登場し、DOMのサブツリー内の要素のみを選択する方法を提供します。
@scopeの紹介
@scopeを使用すると、特定のDOMサブツリー内の要素を選択でき、オーバーライドが困難な過度に特異的なセレクタを書くことなく、またDOM構造に緊密に結合することなく、要素を正確にターゲットにすることができます。
簡単な例で@scopeの概念を理解してみましょう:
上記のHTMLで、.cardコンポーネント内のimg要素に特定のスタイルを適用したい場合、セレクタをimgとして設定することはできません。なぜなら、それはページ全体のすべての画像要素を選択してしまうからです。また、.card > imgのようなCSSセレクタを書くと、直接の子結合子に依存し、DOM構造に密接に結びついてしまいます。マークアップが変更された場合、CSSも変更する必要があります。
ここで重要なのは、DOMの構造を暗黙的にCSSに結びつけることなく、必要な要素のみをターゲットにする正しいバランスを見つけることです。
@scopeを使用すると、セレクタの範囲を制限できます。.cardコンポーネント内の要素のみをターゲットにするには、.cardを@scope at-ruleのスコープルートとして設定します。
結果は以下のようになります:
@scopeの境界を設定することもできます。以下のようなテンプレートがあるとします:
そして、.cardと.card-content要素の間に配置された要素をターゲットにしたい場合:
これにより、.card内にあるが.card_content内にはない要素のみに焦点を当てます。結果は以下のようになります:
別のシナリオを見てみましょう。
例えば、次のようなHTMLがある場合:
.alphaと.betaコンポーネント内の
要素のみをターゲットにするには、.alphaと.betaを@scope at-ruleのスコープルートとして設定する必要があります:
これにより、スタイルが.alphaと.betaのコンテキストにスコープされます。
:scopeは、実際のalphaまたはbeta要素を指す特別な疑似クラスです。
最近の他の機能が@scopeと興味深い方法で重なっています: - @layerを使用して、異なるスタイリングの関心事をグループ化し、優先順位付けします。これらは通常、より広範で構造的なもの(リセット、フレームワーク、デザインシステム、ユーティリティ)であり、任意の数のコンポーネントに適用されます。ボタンコンポーネントとテーマコンポーネントの両方が'default'レイヤーから始まる可能性があります。 - スコープルートは、@container クエリのための良いコンテナ要素になることがよくあります。多くの@scopeルールの先頭で:scope { container: my-scope-name / inline-size; }を見ることが一般的になると予想されます。
まとめ
- @scopeを使用すると、特定のDOMサブツリー内でスタイルを分離できます。
- @scopeは、過度に具体的なセレクタの必要性を減らします。
- @scopeで定義した特定のプロパティが子要素に継承される場合、@scopeの下限を超えて継承されます。
- @scopeを使用して、特定のパターンやコンポーネントとそのブロック-要素の関係を定義します。これらは広範(全体的なテーマ)または狭い(単一のボタン)場合があり、時に重複することもあります。要素が複数のスコープに属することは問題ありませんが、各スコープはDOMの特定のフラグメントに固有のものです。
- ネスティングは、複雑なセレクタをより読みやすくするために存在します。@scopeよりも広範なセレクタを処理できます。なぜなら、特定のユースケース用に設計されていないからです。@scopeはブロック-要素の関係を表現するのに優れていますが、ネスティングは要素--修飾子の関係(疑似クラスなど)に対して明らかに優れた選択肢です。