カスケード レイヤがブラウザに登場

カスケード レイヤ(@layer CSS ルール)は、Chromium 99、Firefox 97、Safari 15.4 ベータ版で利用可能になります。これにより、CSS ファイルをより明示的に制御し、スタイル固有の競合を防ぐことができます。これは、大規模なコードベース、デザイン システム、アプリケーションでサードパーティのスタイルを管理する場合に特に便利です。

CSS を明確にレイヤリングすることで、予期しないスタイルのオーバーライドを防ぎ、優れた CSS アーキテクチャを実現できます。

CSS の限定性とカスケード

CSS の詳細度は、どの要素にどのスタイルを適用するかを CSS が決定する方法です。使用できるさまざまなセレクタによって、スタイルルールの特定性が決まります。たとえば、要素はクラスや属性よりも特定度が低く、クラスや属性は ID よりも特定度が低くなります。これは CSS 学習の基本です。

意図せず特定の要素をオーバーライドしないように、BEM などの CSS 命名規則が使用されています。すべてに単一のクラス名を指定すると、すべてが同じ特定度プレーンに配置されます。ただし、特にサードパーティのコードやデザイン システムを扱う場合は、このような整理されたスタイルを維持できない場合があります。

クラスのあるカードの BEM ビジュアル
keepinguptodate.com の BEM 命名の例(イラスト付き)

カスケード レイヤは、この問題を解決することを目的としています。CSS カスケードに新しいレイヤを導入します。レイヤリングされたスタイルでは、レイヤの優先度は常にセレクタの特異性よりも優先されます。

たとえば、セレクタ .post a.link.card a よりも特異性が高いタイプです。カード内のリンクにスタイルを適用する場合、より具体的なセレクタが適用されます。

@layer を使用すると、各スタイルの詳細度を明示的に指定できます。これにより、すべての CSS が同じプレーンにあっても、数値的には詳細度が低い場合でも、カードリンクのスタイルが投稿リンクのスタイルをオーバーライドするようにできます。これは、カスケードの優先順位が原因です。レイヤリング スタイルを使用すると、新しいカスケード「プレーン」が作成されます。

UI の分割に関するプロジェクトのデモのイラスト

@layer の使用例

インポート時のリンクの色を示すデモ
Codepen のデモをご覧ください。

この例では、@layer を使用して、カスケード レイヤの強力な機能を紹介します。いくつかのリンクが表示されます。追加のクラス名が適用されていないリンク、.link クラスが適用されているリンク、.pink クラスが適用されているリンクがあります。次に、CSS によって basetypographyutilities の 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 */
  }
}

最終的には、すべてのリンクが緑色またはピンク色になります。これは、.linka よりもセレクタレベルの限定性が高く、優先度の高い @layera のカラースタイルが存在するためです。緑色のルールが青色のルールの後のレイヤにある場合、a { color: green }.link { color: blue } をオーバーライドします。

レイヤの優先度が要素の特定度よりも優先されます。

レイヤの整理

上記のように、レイヤはページ上で直接整理することも、ファイルの上部で整理することもできます。

レイヤの順序は、各レイヤ名がコードに最初に現れた順に決まります。

つまり、ファイルの上に次のように追加すると、リンクはすべて赤色で表示され、クラス .link のリンクは青色で表示されます。

@layer utilities, typography, base;

これは、レイヤの順序が逆になり、ユーティリティが最初に、ベースが最後に表示されるようになったためです。したがって、base レイヤのスタイルルールは、タイポグラフィ レイヤのスタイルルールよりも常に優先度が高くなります。緑色のリンクではなく、赤色または青色のリンクになります。

Codepen プロジェクトのスクリーンショット
Codepen のデモをご覧ください。

インポートの整理

@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 */

上記のコード スニペットには、baselayoutscomponents の 3 つのレイヤがあります。base の正規化、テーマ、タイポグラフィ ファイル、layoutspost ファイル、componentscardsfooter の両方。ファイルのインポート時に、レイヤ関数を使用してレイヤがインスタンス化されます。別の方法として、インポートの前にレイヤを宣言して、ファイルの上部にレイヤを整理することもできます。

@layer base,
       theme,
       layouts,
       components,
       utilities;

これで、スタイルを @import する順序はレイヤの順序に関係しなくなります。これは、レイヤ名の最初のインスタンスですでに確立されているためです。心配事が一つ減りましたね。インポートしたファイルを特定のレイヤに設定することはできますが、順序はすでに決まっています。

Codepen プロジェクトのスクリーンショット
Codepen でプロジェクトを探索

レイヤとカスケード

一歩引いて、より広範なカスケードに関連して、レイヤがどこで使用されているかを見てみましょう。

カスケードのイラスト

優先順位は次のとおりです。

  • ユーザー エージェント(通常)(優先度が最も低い)
  • ローカル ユーザー @layer
  • ローカルユーザー(通常)
  • 作成者 @layers
  • 著者: 通常
  • 作成者 !important
  • 作成者 @layer !important
  • ローカルユーザー !important
  • ユーザー エージェント !important**(優先度が最も高い)

@layer !important のスタイルが反転していることがわかります。レイヤリングされていない(通常の)スタイルよりも特定性が低いわけではなく、優先度が高くなります。これは、!important がカスケード内でどのように機能するかによるものです。!important は、スタイルシートの通常のカスケードを破り、通常のレイヤレベルの特定性(優先度)を逆にします。

ネストされたレイヤ

レイヤは他のレイヤ内にネストすることもできます。次の例は、Miriam Suzanne のカスケード レイヤの説明から引用したものです。

@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 を使用しないでください

カスケード レイヤではスコープの問題は解決されません。@layercard.css など)を含む CSS ファイルがあり、カード内のすべてのリンクにスタイルを適用する場合は、次のようなスタイルを記述しないでください。

a {
  
}

これにより、ファイル内のすべての a タグにこのオーバーライドが適用されます。スタイルを適切にスコープすることは引き続き重要です。

.card a {
  
}

ルール 2: カスケード レイヤは、レイヤ化されていない CSS の後に並べられます

レイヤ化された CSS ファイルは、レイヤ化されていない CSS をオーバーライドしません。これは、既存のコードベースをより合理的な方法で操作するために、レイヤを簡単に導入できるように意図的に決定されたものです。たとえば、reset.css ファイルを使用することは、カスケード レイヤの開始点とユースケースとして適しています。

ルール 3: !important はカスケードの特定性を反転します

レイヤリングされたスタイルは、通常、レイヤリングされていないスタイルよりも特定性が低くなりますが、!important を使用すると、この点が逆になります。レイヤでは、!important ルールを使用した宣言は、レイヤなしのスタイルよりもより具体的です。

その場合、!important スタイルは特定度を反転します。上記の図は、これを示しています。author @layer は author normal よりも優先度が低く、author normal は author !important よりも優先度が低く、author !important は author @layer !important よりも優先度が低くなります。

レイヤが複数ある場合、!important を含む最初のレイヤが !important の優先度を持ち、最も具体的なスタイルになります。

ルール 4: 挿入ポイントを理解する

レイヤの順序は、各レイヤ名がコードに初めて現れたときに確立されるため、layer() のインポートと設定の後、または別の @layer ステートメントの後に @layer 宣言を配置した場合、その宣言は無視されます。CSS とは異なり、ページの一番下にあるスタイルルールがカスケード レイヤに適用されるのではなく、最初のインスタンスで順序が確立されます。

リスト、レイヤ ブロック、インポートに含めることができます。layer() を含むインポートリストの後に @layer を配置しても、何も実行されません。ファイルを先頭に配置すると、レイヤの順序が設定され、アーキテクチャ内のレイヤを明確に確認できます。

ルール 5: 具体的に表現する

カスケード レイヤでは、より具体的でないセレクタ(a など)が、より具体的なセレクタ(.link など)をオーバーライドします。この場合、より具体的でないセレクタがより具体的なレイヤ上にある必要があります。次の点を考慮してください。

@layer utilities, components が指定されている場合、layer(components)alayer(utilities).pink をオーバーライドします。これは API の一部として意図された動作ですが、予期していないと混乱や不満が生じる可能性があります。

そのため、ユーティリティ クラスを作成する場合は、オーバーライドするコンポーネントよりも上位のレイヤとして常に含めてください。「色を変更するために .pink クラスを追加したばかりなのに、適用されない」と思われるかもしれません。

カスケード レイヤの詳細

カスケード レイヤの詳細については、以下のリソースもご覧ください。