カスケード レイヤ(@layer
CSS ルール)は、Chromium 99、Firefox 97、Safari 15.4(ベータ版)に導入される予定です。CSS ファイルをより明示的に制御して、スタイル固有の競合を防止できます。これは、大規模なコードベースやデザイン システム、アプリケーションでサードパーティのスタイルを管理する場合に特に便利です。
CSS を明確にレイヤ化することで、予期せぬスタイルのオーバーライドを防ぎ、CSS アーキテクチャを改善できます。
CSS の特異性とカスケード
CSS 限定性とは、CSS がどのスタイルをどの要素に適用するかを決定する仕組みです。使用できるセレクタによって、スタイルルールの特異性が決まります。たとえば、要素はクラスや属性ほど限定的ではなく、クラスや属性よりも限定的ではありません。これは CSS 学習の構成要素です。
多くの場合、BEM などの CSS の命名規則を使用することによって、具体性を意図せずオーバーライドしてしまうことを防ぎます。すべてに同じクラス名を付けると、すべてが同じ特異性プレーンに配置されます。しかし、特にサードパーティのコードやデザイン システムを使用する場合、そのような整理されたスタイルを維持することは必ずしも不可能です。
カスケード レイヤはこの問題を解決することを目的としています。CSS カスケードに新しいレイヤが導入されています。レイヤ化スタイルでは、レイヤの優先順位は常にセレクタの特異性に勝ります。
たとえば、セレクタ .post a.link
は .card a
よりも特異性が高くなります。リンクのスタイルを設定しようとしている場合、カード内の投稿内で、より具体的なセレクタが適用されます。
@layer
を使用すると、それぞれのスタイル固有性をより明確に示すことができます。また、すべての CSS が同じ平面上にある場合に、限定性が数値的に低くなる場合でも、カードリンクのスタイルが投稿リンクのスタイルをオーバーライドするようにできます。これはカスケードの優先順位によるものです。レイヤスタイルは、新しいカスケード「平面」を作成します。
@layer
の実例
この例では、@layer
を使用してカスケード レイヤの機能を紹介します。複数のリンクが表示されています。追加クラス名が適用されていないリンク、.link
クラスを含むリンク、.pink
クラスを含むリンクがあります。CSS は、base
、typography
、utilities
の 3 つのレイヤを次のように追加します。
@layer base {
a {
font-weight: 800;
color: red; /* ignored */
}
.link {
color: blue; /* ignored */
}
}
@layer typography {
a {
color: green; /* styles *all* links */
}
}
@layer utilities {
.pink {
color: hotpink; /* styles *all* .pink's */
}
}
最終的には、すべてのリンクが緑色またはピンク色になります。これは、.link
は a
よりもセレクタ レベルの特異性が高い一方、@layer
の優先度が高い a
には色スタイルがあるためです。緑のルールが青のルールの後のレイヤにある場合、a { color: green }
が .link { color: blue }
をオーバーライドします。
レイヤの優先順位は要素の特異性に勝る。
レイヤの編成
上図のようにレイヤをページ上で直接整理することも、ファイルの上部で整理することもできます。
レイヤの順序は、各レイヤ名がコードで初めて登場した時点で設定されます。
つまり、ファイルの先頭に次のコードを追加すると、リンクがすべて赤色になり、クラス .link
のリンクが青色になります。
@layer utilities, typography, base;
これは、レイヤの順序が逆になり、ユーティリティが最初、ベースが最後になるためです。そのため、base
レイヤのスタイルルールは常に、タイポグラフィ レイヤのスタイルルールよりも限定性が高くなります。今後は緑色のリンクではなく、赤または青のリンクになります。
インポートの編成
@layer
のもう 1 つの使用方法は、インポート ファイルを使用することです。これは、スタイルをインポートするときに、次の例のように layer()
関数を使用して直接行うことができます。
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
上のコード スニペットには、base
、layouts
、components
の 3 つのレイヤがあります。base
の正規化ファイル、テーマファイル、タイポグラフィ ファイル。layouts
には post
ファイル、components
には cards
と footer
を使用します。ファイルのインポート時に、layer 関数を使用してレイヤがインスタンス化されます。もう 1 つの方法は、ファイルの先頭でレイヤを整理し、インポートの前にレイヤを宣言することです。
@layer base,
theme,
layouts,
components,
utilities;
スタイルを @import
する順序は、レイヤ名の最初のインスタンスですでに確立されているため、レイヤの順序は重要ではありません。心配する必要が 1 つ減ります。インポートしたファイルを特定のレイヤに設定できますが、順序はすでに設定されています。
レイヤとカスケード
一歩戻って、より広いカスケードに関連してレイヤが使用される場所を見てみましょう。
優先順位は次のとおりです。
- ユーザー エージェントは通常(最も優先順位が低い)
- ローカル ユーザー @layer
- ローカル ユーザー(通常)
- @layers を作成
- 作成者(通常)
- 作成者: 重要
- 作成者 @layer !重要
- ローカル ユーザー !重要
- ユーザー エージェント !important**(最も優先順位が高い)
ここで、@layer !important
のスタイルが反転していることがわかります。レイヤ化されていない(通常の)スタイルよりも限定的ではなく、優先順位が高くなります。これは、カスケードで !important
が機能する仕組みによるものです。スタイルシートの通常のカスケードは解除され、通常のレイヤレベルの特異性(優先順位)が逆になります。
ネストされたレイヤ
レイヤを他のレイヤ内にネストすることもできます。次の例は、Miram Suzanne の Cascade Layers の説明によるものです。
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
上記のコード スニペットでは、framework
内にネストされている default
レイヤの記号として .
を使用して、framework.default
にアクセスできます。これをより簡潔な形式で記述することもできます。
@layer framework.default {
p { margin-block: 0.75em }
}
生成されるレイヤとレイヤの順序は次のとおりです。
- デフォルト
framework.default
framework
レイヤなし- レイヤーなし
注意点
カスケード レイヤは正しく使用すれば素晴らしい効果を発揮しますが、混乱や想定外の結果を招く可能性もあります。カスケード レイヤを操作するときは、次の点に注意してください。
ルール 1: スコープ設定に @layer
を使用しない
カスケード レイヤではスコープ設定を解決できません。@layer
を含む CSS ファイルがあり、card.css
と話しかけ、カード内のすべてのリンクにスタイルを設定する場合は、次のようにスタイルを記述しないでください。
a {
…
}
そうすると、ファイル内のすべての a
タグでこのオーバーライドが行われます。その場合も、スタイルを適切にスコープ設定することが重要です。
.card a {
…
}
ルール 2: カスケード レイヤは非レイヤ化 CSS の背後に並べられる
レイヤ化 CSS ファイルは、レイヤ化されていない CSS より優先されないことに注意してください。これは、既存のコードベースで作業するために、より理にかなった方法でレイヤを簡単に導入できるようにするための意図的な決定です。カスケード レイヤの出発点およびユースケースとしては、たとえば reset.css
ファイルを使用するのがよいでしょう。
ルール 3: !important
はカスケード特異性を反転する
一般的に、レイヤ化スタイルはレイヤ化されていないスタイルほど限定的ではありませんが、!important
を使用すると逆になります。レイヤ内では、!important
ルールによる宣言は、レイヤ化されていないスタイルよりも限定的です。
その場合、!important
スタイルはその特異性を反転します。上の図に参考として示します。作成者の @layers は作成者の通常よりも優先度が低く、作成者の !important よりも優先度が低く、作成者の @layer !important よりも優先度が低くなります。
レイヤが複数ある場合は、!important
の最初のレイヤが !important
の優先順位となり、最も狭い範囲のスタイルになります。
ルール 4: インジェクション ポイントを理解する
レイヤの順序は、各レイヤ名が初めてコードに登場した時点で設定されるため、layer()
をインポートして設定した後や、別の @layer
ステートメントの後に @layer
宣言を配置しても、無視してかまいません。ページの一番下にあるスタイルルールがカスケード レイヤに適用される CSS とは異なり、順序は最初に確立されます。
これは、リスト、レイヤ ブロック、インポートのいずれかです。layer()
でインポート リストの後に @layer
を追加しても、何も起こりません。ファイルの先頭に配置すると、レイヤの順序が設定され、アーキテクチャ内のレイヤを明確に確認できるようになります。
ルール 5: 独自性に注意する
カスケード レイヤでは、具体的でないセレクタ(a
など)が、より具体的なレイヤにある具体的でないセレクタ(.link
など)をオーバーライドします。次の点にご注意ください。
@layer utilities, components
が指定されている場合、layer(components)
の a
は layer(utilities)
の .pink
をオーバーライドします。これは API の意図的な部分ですが、想定していないと混乱や不満が生じる可能性があります。
そのため、ユーティリティ クラスを記述する場合は、オーバーライドするコンポーネントよりも高階レイヤとして必ず含めてください。「色を変更するためにこの .pink
クラスを追加したので、適用されない」と思われるかもしれません。
カスケード レイヤの詳細
カスケード レイヤについて詳しくは、以下のリソースもご覧ください。