1. 導入
この節は規範的ではありません。
このモジュールは、あるスタイル規則の内部に別のスタイル規則をネストすることをサポートする方法を説明します。内側の規則のセレクタは外側の規則で一致した要素を参照できるようになります。この機能により、関連するスタイルを CSS 文書内の単一の構造にまとめることができ、可読性と保守性が向上します。
テスト
ネストの一般的なテスト
- block-skipping.html (ライブテスト) (ソース)
- delete-other-rule-crash.html (ライブ テスト) (ソース)
- double-parent-pseudo-in-placeholder-crash.html (ライブ テスト) (ソース)
- has-nesting.html (ライブテスト) (ソース)
- invalidation-001.html (ライブテスト) (ソース)
- invalidation-002.html (ライブテスト) (ソース)
- invalidation-003.html (ライブテスト) (ソース)
- invalidation-004.html (ライブテスト) (ソース)
- nested-error-recovery.html (ライブ テスト) (ソース)
- nesting-basic.html (ライブテスト) (ソース)
- nesting-revert-rule.tentative.html (ライブ テスト) (ソース)
- parent-pseudo-in-placeholder-crash.html (ライブ テスト) (ソース)
- pseudo-part-crash.html (ライブテスト) (ソース)
- pseudo-where-crash.html (ライブテスト) (ソース)
- supports-is-consistent.html (ライブ テスト) (ソース)
1.1. モジュールの相互作用
このモジュールは [CSS21]
パーサモデルを拡張する新しいパーサ規則を導入します。
また [SELECTORS-4]
モジュールを拡張するセレクタを導入します。
さらに [CSSOM-1]
モジュールで定義されたいくつかの IDL とアルゴリズムを拡張・変更します。
1.2. 値
この仕様は新しいプロパティや値を定義しません。
2. 解説
この節は非規範的です。
よりコンパクトに書きたい CSS があると想像してください。
.foo{ color : green; } .foo .bar{ font-size : 1.4 rem ; }
ネストを使うと、このように書けます:
.foo{ color : green; .bar{ font-size : 1.4 rem ; } }
Sass や他の CSS プリプロセッサでスタイルをネストしてきたなら、とても馴染みがあるでしょう。
親のスタイル規則の内部に任意の規則をネストできます:
main{ div{ ...} .bar{ ...} #baz{ ...} :has ( p) { ...} ::backdrop{ ...} [ lang|="zh" ] { ...} *{ ...} }
デフォルトでは、子規則のセレクタは親規則に対して子孫結合子で接続されるものとみなされますが、ネストされたセレクタを任意の結合子で始めてその接続方法を変更することができます:
main{ + article{ ...} > p{ ...} ~ main{ ...} }
新しい & セレクタは親のセレクタで一致した要素を明示的に参照することを可能にします。したがって、前の例は次のようにも書けます:
main{ & + article{ ...} & > p{ ...} & ~ main{ ...} }
しかし、ネストされたセレクタ内で & を他の位置に置くことで、親と子の規則の間の別の種類の関係を示すこともできます。例えば、次の CSS:
ul{ padding-left : 1 em ; } .component ul{ padding-left : 0 ; }
はネストを使って次のように書き換えられます:
ul{ padding-left : 1 em ; .component &{ padding-left : 0 ; } }
再び、& は「ネストされたセレクタをここに置きたい」ということを示す方法を提供します。
セレクタ同士の間にスペースを入れたくない場合にも便利です。例えば:
a{ color : blue; &:hover{ color : lightblue; } }
このようなコードは と同じ結果を生みます。& がなければ、 となり、a と :hover
の間にスペースが入ってしまい、ホバーリンクにスタイルを適用できなくなります。
複数レイヤーでネストすることも可能です — 既にネストされた CSS の中にさらにネストすることが望む限り何層でもできます。ネストは Container Queries、Supports Queries、Media Queries、Cascade Layers と混在させて使用できます。ほとんど何でも何の中にも入れられます。
3. ネストされたスタイル規則
スタイル規則は他のスタイル規則の内部にネストできます。これらの ネストされたスタイル規則 は通常のスタイル規則とまったく同じように動作します — セレクタを介して要素にプロパティを関連付けます — が、親規則のセレクタコンテキストを「継承」し、親のセレクタを繰り返すことなく(場合によっては複数回)そのセレクタに基づいてさらに構築できるようにします。
ネストされたスタイル規則 は通常のスタイル規則とまったく同じですが、相対セレクタ を使用でき、それらは暗黙的に親規則で一致した要素に対して相対的です。
テスト
.foo{ color : red; a{ color : blue; } }
は有効であり、次と同等です:
.foo{ color : red; } .foo a{ color : blue; }
ネストされた規則はまた ネストセレクタ を使って親規則で一致した要素を直接参照したり、相対セレクタ 構文を用いて「子孫」以外の関係を指定することもできます。
.foo{ color : red; &:hover{ color : blue; } } /* equivalent to: */ .foo{ color : red; } .foo:hover{ color : blue; }
.foo{ color : red; + .bar{ color : blue; } } /* equivalent to: */ .foo{ color : red; } .foo + .bar{ color : blue; }
3.1. 構文
スタイル規則の内容 (style rule) は、既存の 宣言 に加えて、ネストされたスタイル規則 と アットルール を受け入れるようになりました。
ネストされたスタイル規則 は非ネスト規則と以下の点で異なります:
-
ネストされたスタイル規則 は、その前置部分として <relative-selector-list> を受け入れます(従来の <selector-list> の代わりに)。任意の 相対セレクタ は ネストセレクタ で表される要素に対して相対的です。
-
もし <relative-selector-list> の中のセレクタが結合子で始まらず、かつ ネストセレクタを含む 場合、それは非 相対セレクタ として解釈されます。
ネストされたスタイル規則がどのように解析されるかの詳細は [CSS-SYNTAX-3] に定義されています。
無効な ネストされたスタイル規則 は、その内容とともに無視されますが、親規則自体を無効にすることはありません。
相対セレクタ を持つネスト規則は、暗黙的に含まれる ネストセレクタ の特異性を含みます。例えば、.foo { > .bar {...}} と .foo { & > .bar {...}} は内側の規則に対して同じ特異性を持ちます。
例えば、あるコンポーネントがクラス .foo を使い、ネストされたコンポーネントが .fooBar を使う場合、Sass では次のように書けます:
.foo{ color : blue; &Bar{ color : red; } } /* In Sass, this is equivalent to .foo { color: blue; } .fooBar { color: red; } */
これは CSS では許されません。ネストは構文変換ではなく、親セレクタが実際に一致する要素に対してマッチするためです。
また、セレクタ &Bar はそもそも CSS では無効です。なぜなら Bar の部分はタイプセレクタであり、複合セレクタの中では先頭に来なければならないからです。(つまり Bar& のように書く必要があります。)したがって幸いにも、CSS ネストとプリプロセッサ構文には重なりはありません。
注: これは :is(:unknown(&), .bar) のようなケースも検出するために明示的に表現されています。未知のセレクタ(未知であるため、その引数がセレクタとして解析される意図なのかどうかを知る手段がない)がネストセレクタを含む唯一の部分である場合でも、それは将来のブラウザで有効になる可能性があり、パースを無関係なバージョン依存にしたくないため、そのような場合もネストセレクタを含むものとして扱います。
もし <forgiving-selector-list> の項目が ネストセレクタを含む が無効である場合、その項目は破棄されずそのまま正確に保持されます。(これはセレクタのマッチ動作を変えるものではありません — 無効なセレクタは依然として何にもマッチしません — ただしシリアライズの結果が変わるだけです。)
前の段落は & 自体を Selectors に移動するときに Selectors 側に移す必要があります。ここでは便宜上モンキーパッチしています。
3.2. 例
/* & can be used on its own */ .foo{ color : blue; & > .bar{ color : red; } > .baz{ color : green; } } /* equivalent to .foo { color: blue; } .foo > .bar { color: red; } .foo > .baz { color: green; } */ /* or in a compound selector, refining the parent’s selector */ .foo{ color : blue; &.bar{ color : red; } } /* equivalent to .foo { color: blue; } .foo.bar { color: red; } */ /* multiple selectors in the list are all relative to the parent */ .foo, .bar{ color : blue; + .baz, &.qux{ color : red; } } /* equivalent to .foo, .bar { color: blue; } :is(.foo, .bar) + .baz, :is(.foo, .bar).qux { color: red; } */ /* & can be used multiple times in a single selector */ .foo{ color : blue; & .bar & .baz & .qux{ color : red; } } /* equivalent to .foo { color: blue; } .foo .bar .foo .baz .foo .qux { color: red; } */ /* & doesn’t have to be at the beginning of the selector */ .foo{ color : red; .parent &{ color : blue; } } /* equivalent to .foo { color: red; } .parent .foo { color: blue; } */ .foo{ color : red; :not ( &) { color : blue; } } /* equivalent to .foo { color: red; } :not(.foo) { color: blue; } */ /* But if you use a relative selector , an initial & is implied automatically */ .foo{ color : red; + .bar + &{ color : blue; } } /* equivalent to .foo { color: red; } .foo + .bar + .foo { color: blue; } */ /* Somewhat silly, but & can be used all on its own, as well. */ .foo{ color : blue; &{ padding : 2 ch ; } } /* equivalent to .foo { color: blue; } .foo { padding: 2ch; } // or .foo { color: blue; padding: 2ch; } */ /* Again, silly, but can even be doubled up. */ .foo{ color : blue; &&{ padding : 2 ch ; } } /* equivalent to .foo { color: blue; } .foo.foo { padding: 2ch; } */ /* The parent selector can be arbitrarily complicated */ .error, #404{ &:hover > .baz{ color : red; } } /* equivalent to :is(.error, #404):hover > .baz { color: red; } */ .ancestor .el{ .other-ancestor &{ color : red; } } /* equivalent to .other-ancestor :is(.ancestor .el) { color: red; } /* As can the nested selector */ .foo{ &:is ( .bar, &.baz) { color : red; } } /* equivalent to .foo :is(.bar, .foo.baz) { color: red; } */ /* Multiple levels of nesting "stack up" the selectors */ figure{ margin : 0 ; > figcaption{ background : hsl ( 0 0 % 0 % /50 % ); > p{ font-size : .9 rem ; } } } /* equivalent to figure { margin: 0; } figure > figcaption { background: hsl(0 0% 0% / 50%); } figure > figcaption > p { font-size: .9rem; } */ /* Example usage with Cascade Layers */ @layer base{ html{ block-size : 100 % ; body{ min-block-size : 100 % ; } } } /* equivalent to @layer base { html { block-size: 100%; } html body { min-block-size: 100%; } } */ /* Example nesting Cascade Layers */ @layer base{ html{ block-size : 100 % ; @layer support{ body{ min-block-size : 100 % ; } } } } /* equivalent to @layer base { html { block-size: 100%; } } @layer base.support { html body { min-block-size: 100%; } } */ /* Example usage with Scoping */ @scope ( .card) to( > header) { :scope{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; > header{ border-block-end : 1 px solid white; } } } /* equivalent to @scope (.card) to (> header) { :scope { inline-size: 40ch; aspect-ratio: 3/4; } :scope > header { border-block-end: 1px solid white; } } */ /* Example nesting Scoping */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; @scope ( &) to( > header > *) { :scope > header{ border-block-end : 1 px solid white; } } } /* equivalent to .card { inline-size: 40ch; aspect-ratio: 3/4; } @scope (.card) to (> header > *) { :scope > header { border-block-end: 1px solid white; } } */
3.3. 他のアットルールのネスト
ネストされたスタイル規則 に加えて、 この仕様は ネストされたグループ規則 を スタイル規則 の内部に許可します: 本文に スタイル規則 を含む任意のアットルールは、 別段の指定がない限り スタイル規則 の内部にネストできます。
このようにネストされた場合、 ネストされたグループ規則 のブロックの内容は <block-contents> として解析され、<rule-list> とはなりません:
-
スタイル規則 は ネストされたスタイル規則 であり、 その ネストセレクタ は最も近い祖先の スタイル規則 から定義を受けます。
-
プロパティは直接使用でき、あたかも ネストされた宣言規則 にネストされているかのように振る舞います。
テスト
そのような ネストされたグループ規則 の意味と挙動は、 別段の指定がない限りそれ以外は変更されません。
/* プロパティは直接使用できます */ .foo{ display : grid; @media ( orientation: landscape) { grid-auto-flow : column; } } /* 等価: */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column} } /* またネストされていないものとも等価: */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column; } } /* 条件付きルールはさらにネストできます */ .foo{ display : grid; @media ( orientation: landscape) { grid-auto-flow : column; @media ( min-width >1024 px ) { max-inline-size : 1024 px ; } } } /* 等価 */ .foo{ display : grid; } @media ( orientation: landscape) { .foo{ grid-auto-flow : column; } } @media ( orientation: landscape) and( min-width >1024 px ) { .foo{ max-inline-size : 1024 px ; } } /* ネストされた Cascade Layers の例 */ html{ @layer base{ block-size : 100 % ; @layer support{ & body{ min-block-size : 100 % ; } } } } /* 等価 */ @layer base{ html{ block-size : 100 % ; } } @layer base.support{ html body{ min-block-size : 100 % ; } } /* ネストされた Scoping の例 */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; @scope ( &) { :scope{ border : 1 px solid white; } } } /* 等価 */ .card{ inline-size : 40 ch ; aspect-ratio : 3 /4 ; } @scope ( .card) { :scope{ border-block-end : 1 px solid white; } }
直接ネストされたプロパティが連続している場合、それらは自動的に ネストされた宣言規則 でラップされます。 (これは CSSOM で観察できます。)
3.3.1. ネストされた @scope 規則
@scope ルールが ネストされたグループ規則 である場合、 & が <scope-start> セレクタ内にあるとき、 それは最も近い祖先スタイル規則で一致した要素を参照します。
.parent{ color : blue; @scope ( & > .scope) to( & .limit) { & .content{ color : red; } } }
次と等価です:
.parent{ color : blue; } @scope ( .parent > .scope) to( :where ( :scope) .limit) { :where ( :scope) .content{ color : red; } }
3.4. ネスト規則と宣言の混在
あるスタイル規則が宣言と ネストされたスタイル規則 や ネストされたグループ規則 の両方を含む場合、 それら三者は任意に混在できます。 規則の後や規則の間に来る宣言は、 他の規則に対する順序を保持するために暗黙的に ネストされた宣言規則 でラップされます。
article{ color : green; &{ color : blue; } color: red; } /* 等価 */ article{ color : green; } :is ( article) { color : blue; } article{ color : red; } /* 等価ではない */ article{ color : green; } article{ color : red; } :is ( article) { color : blue; }
「出現順序(Order Of Appearance)」を決定する目的のために、ネストされたスタイル規則 と ネストされたグループ規則 は、その親規則の後に来るものと見なされます。
article{ color : blue; &{ color : red; } }
両方の宣言は同じ特異性 (0,0,1) を持ちますが、 ネストされた規則は親規則の後に来ると見なされるため、 color: red の宣言がカスケードで勝ちます。
一方、次の例では:
article{ color : blue; :where ( &) { color : red; } }
:where() 疑似クラスはネストセレクタの特異性を 0 に減らすため、 ネストセレクタ を含む宣言である color: red は特異性が (0,0,0) となり、 「出現順序」が考慮される前に color: blue の宣言に負けます。
注意:宣言とネストされたルールを自由に組み合わせることは可能ですが、 後のプロパティが自動的にネストされた宣言ルールに 包まれるため、読みづらく多少混乱を招くことがあります。 可読性のために、著者はスタイルルール内のすべてのプロパティを ネストルールの前に配置することを推奨します。 (これは古いユーザーエージェントでも若干有利に働きます: パースやエラー回復の仕組みによって、ネストルールの後に出現するプロパティが スキップされることがあるためです。)
4. ネストセレクタ: & セレクタ
ネストされたスタイル規則を使用する際には、 親規則で一致した要素を参照できる必要があります; それこそがネストの目的の全てです。 それを実現するために、 この仕様は新しいセレクタ、ネストセレクタを定義します。 表記は & (U+0026 AMPERSAND) です。
ネストされたスタイル規則 のセレクタで使用された場合、 ネストセレクタは 親規則で一致した要素を表します。 他の文脈で使用された場合は、 その文脈における :scope と同じ要素を表します (別段の定義がない限り)。
a, b{ & c{ color : blue; } }
は次と等価です
:is ( a, b) c{ color : blue; }
ネストセレクタは 疑似要素を表すことはできません (これは :is() 疑似クラスの挙動と同じです)。
.foo, .foo::before, .foo::after{ color : red; &:hover{ color : blue; } }
アンパサンド(&)は .foo にマッチする要素のみを表します; 言い換えれば、次と等価です:
.foo, .foo::before, .foo::after{ color : red; } .foo:hover{ color : blue; }
この制限を緩和したいと考えていますが、 :is() と & の両方を同時に扱う必要があるため、 それらは同じ内部メカニズムに基づいて意図的に構築されています。 (Issue 7433)
特異性は、ネストセレクタのものは、 親スタイル規則のセレクタリスト内の複合セレクタ群のうち最大の特異性に等しいです (これは :is() の挙動と同じです)、 もしそのようなセレクタリストが存在しない場合は 0 になります。
#a, b{ & c{ color : blue; } } .foo c{ color : red; }
次のような DOM 構造では
< b class = foo > < c > Blue text</ c > </ b >
テキストは赤ではなく青になります。 & の特異性は #a([1,0,0])と b([0,0,1])のうち大きい方であり、 したがって [1,0,0] になり、 全体の & c セレクタの特異性は [1,0,1] となり、 .foo c([0,1,1]) より大きくなります。
注目すべきは、これはネストを手動で展開して非ネスト規則にした場合とは異なる結果になる点です。 その場合、color: blue の宣言は b c セレクタ([0,0,2])によってマッチすることになり、 #a c([1,0,1])ではありません。
なぜ特異性が非ネスト規則と異なるのか?
ネストセレクタは意図的に :is() 疑似クラスと同じ特異性ルールを使用します。 すなわち引数の中で最大の特異性を使用し、 実際にどのセレクタがマッチしたかを追跡しません。
これはパフォーマンス上の理由で必要です; セレクタがマッチした方法に応じて複数の可能な特異性を持つと、 セレクタマッチの処理が非常に複雑かつ遅くなります。
それでも疑問は残ります: なぜ & を :is() に基づいて定義するのでしょうか? Nesting っぽい機能を持つ一部の非ブラウザ実装は :is() にデシュガーしないことがあり、 主にそれらは :is() の導入以前に存在したためです。 代わりに直接展開(desugar)します; しかしそれは重大な問題をもたらします — いくつかの(比較的一般的な)ケースで 可能性の組み合わせが指数的に爆発し、巨大なセレクタを偶然生成することがあるのです。
.a1, .a2, .a3{ .b1, .b2, .b3{ .c1, .c2, .c3{ ...; } } } /* 単純にデシュガーすると */ .a1 .b1 .c1, .a1 .b1 .c2, .a1 .b1 .c3, .a1 .b2 .c1, .a1 .b2 .c2, .a1 .b2 .c3, .a1 .b3 .c1, .a1 .b3 .c2, .a1 .b3 .c3, .a2 .b1 .c1, .a2 .b1 .c2, .a2 .b1 .c3, .a2 .b2 .c1, .a2 .b2 .c2, .a2 .b2 .c3, .a2 .b3 .c1, .a2 .b3 .c2, .a2 .b3 .c3, .a3 .b1 .c1, .a3 .b1 .c2, .a3 .b1 .c3, .a3 .b2 .c1, .a3 .b2 .c2, .a3 .b2 .c3, .a3 .b3 .c1, .a3 .b3 .c2, .a3 .b3 .c3{ ...}
ここでは、3 レベルのネストがあり、 各レベルに 3 つのセレクタがあるため、 27 個の展開セレクタが生成されました。 リストにさらにセレクタを加えたり、 ネストのレベルを増やしたり、 ネスト規則をより複雑にすると、 比較的小さな規則が数メガバイト(あるいはそれ以上)のセレクタに拡張されることがあります。
一部の CSS ツールはヒューリスティックにいくつかの組み合わせを破棄することで最悪ケースを回避し、 出力を減らして「おそらく」正しい結果にしますが、 それは UA にとって許容できる選択肢ではありません。
:is() を使ったデシュガーは この問題を完全に排除しますが、 その代償として特異性が多少有用性を失うことになり、 それが妥当なトレードオフだと判断されました。
ネストセレクタは、 親規則でマッチしていた場合に限り、特徴のない(featureless) 要素にもマッチできます。
ネストセレクタが複合セレクタ内にある位置は 振る舞いに差を与えません (つまり &.foo と .foo& は同じ要素にマッチします)、 ただし既存のルールである、タイプセレクタ が存在する場合は複合セレクタの先頭に来なければならない という規則は引き続き適用されます (つまり &div は不正であり、代わりに div& と書く必要があります)。
テスト
- contextually-invalid-selectors-001.html (ライブテスト) (ソース)
- contextually-invalid-selectors-002.html (ライブテスト) (ソース)
- contextually-invalid-selectors-003.html (ライブテスト) (ソース)
- host-nesting-001.html (ライブテスト) (ソース)
- host-nesting-002.html (ライブテスト) (ソース)
- host-nesting-003.html (ライブテスト) (ソース)
- host-nesting-004.html (ライブテスト) (ソース)
- host-nesting-005.html (ライブテスト) (ソース)
- nesting-type-selector.html (ライブテスト) (ソース)
5. ネストされた宣言ルール
やや技術的な理由から、 スタイル規則の内容の先頭に現れるプロパティと 他の規則と入り混じって現れるプロパティを区別できることが重要です。
.foo{ color : red; @media ( ...) { ...} background: blue; }
我々は color: red
と background: blue を少し異なって扱う必要があります。
特に、CSSOM では、
color: red はスタイル規則の style
属性に公開されますが、
background: blue は代わりに
cssRules
リストに表示される必要があります。
これを実現するために、CSS の解析はこのようなプロパティを自動的に特別な子規則でラップします。 しかし、それらを スタイル規則 として、 & セレクタでラップすると、 いくつか望ましくない挙動が発生します:
.foo, .foo::before{ color : red; &{ background : blue; } }
ネストされた規則は background を .foo::before 要素に適用しません。 その理由はアンパサンド(&)が疑似要素を表せないためです。
同様に、ネストされた非スタイル規則の子宣言は何らかの方法で 規則 として公開される必要があります。
というのも、これらの種類の規則(例えば @media)はこれまで style
プロパティを持たなかったからです。
これらは上記と同じ問題に直面します。
これらすべての問題に対処するために、 我々は直接ネストされた連続するプロパティの列を ネストされた宣言規則でラップします。
別段の指定がない限り、 ネストされた宣言規則は ネストされたスタイル規則であり、 他のスタイル規則と同一に動作します。 それは親スタイル規則とまったく同じ要素と疑似要素にマッチし、 同じ特異性の振る舞いを持ちます。(これは & セレクタを持つスタイル規則と類似していますが、上で説明したようにやや強力です。)
なぜ ネストされた宣言規則 が存在するのか?
元々は、この仕様はスタイル規則内のすべての宣言をまとめ、 それらを規則の先頭に置かれたかのように「移動」していました。 また生の宣言を ネストされたグループ規則 の中で自動的に平文のスタイル規則でラップし、 & セレクタを使用していました。
我々が ネストされた宣言規則 に切り替えた理由は主に二つあります。
第一に、& {...} 規則を使って暗黙的に宣言を ネストされたグループ規則 にラップすることは挙動を変えてしまいます。 このノートの後の例に示されるように、 親スタイル規則が疑似要素を含む場合に破綻し、 それがない場合でもネストされた宣言の特異性の振る舞いを変える可能性があります。 ネストされた宣言規則 に切り替えることでこれらの問題を避け、 ネストされた @media 等の振る舞いを *非ネストの* @media 等と同一にします。
第二に、将来の CSS 機能(特に「ミキシン」)のいくつかの詳細は、 宣言が自動的にスタイル規則の先頭に移動されると正しく動作しません。 我々はそれらの宣言を他の規則との相対的な順序を保持する必要があり、 それを CSSOM で表現するためには何らかのルールでラップする必要があります。 単に通常の & {...} 規則を使うと前段の問題が再発するため、 ネストされた宣言規則 を用いることで副作用なしにこれを可能にしています。
.foo, .foo::before, .foo::after{ color : black; @media ( prefers-color-scheme: dark) { &{ color : white; } } }
ダークモードのページでは、 .foo 要素のテキスト色は白に変わりますが、 ::before と ::after 疑似要素は黒のままになります。 その理由は & セレクタが疑似要素を表せないためです。
しかし、代わりに次のように書かれていた場合:
.foo, .foo::before, .foo::after{ color : black; @media ( prefers-color-scheme: dark) { color : white; } }
その場合、color: white は暗黙的に ネストされた宣言規則でラップされ、 その子規則は親のスタイル規則と正確に同じものにマッチすることが保証されるため、 要素とその疑似要素の両方がダークモード時に白いテキストになります。
.foo{ color : black; @media ( ...) { ...} background: silver; }
もし .foo ルールの CSSOM オブジェクトを調べると、
その style
属性には宣言は一つだけ入っています:
color: black です。
background: silver の宣言は
暗黙的に作成された ネストされた宣言の子規則 に見つかります、
位置は fooRule です。
テスト
- mixed-declarations-rules.html (visual test) (ソース)
- nested-declarations-cssom-whitespace.html (ライブテスト) (ソース)
- nested-declarations-cssom.html (ライブテスト) (ソース)
- nested-declarations-matching.html (ライブテスト) (ソース)
6. CSSOM
注: [CSSOM-1] は現在、
CSSStyleRule
が子規則を持てることを定義しています。
ネストされた 相対セレクタ を ネストされたスタイル規則 内でシリアライズする際、 そのセレクタは絶対化され、 暗黙の ネストセレクタ が挿入されなければなりません。
6.1. The CSSNestedDeclarations
Interface
The CSSNestedDeclarations
interface は ネストされた宣言規則 を表します。
[Exposed =Window ]interface :CSSNestedDeclarations CSSRule { [SameObject ,PutForwards =cssText ]readonly attribute CSSStyleProperties style ; };
style attribute
はルールのための CSSStyleProperties
オブジェクトを返さなければならず、次のプロパティを持ちます:
- computed flag
-
未設定
- readonly flag
-
未設定
- declarations
-
ルール内の宣言。指定順序 に従います。
- parent CSS rule
- owner node
-
Null
The CSSNestedDeclarations
ルールは、その 宣言ブロック が直接 シリアライズされたかのようにシリアライズされます。
注: これは、隣接する複数の ネストされた宣言規則(例えば insertRule
で作成可能)が、
シリアライズして再解析すると単一の規則に折りたたまれることを意味します。
プライバシー上の考慮事項
この仕様に関して新たなプライバシー上の考慮事項は報告されていません。
セキュリティ上の考慮事項
この仕様に関して新たなセキュリティ上の考慮事項は報告されていません。
7. 変更点
2023年2月14日の作業草案(Feb 14, 2023 Working Draft)以降の主な変更点:
-
<scope-start> セレクタを持つ @scope ルールは、 もはやネストにおける親規則として振る舞いません。 (Issue 9740)
-
ネストセレクタ が featureless 要素にマッチ可能であることを明確化しました。
-
&div を無効に戻しました; いまや Syntax が「無限ルックアヘッド」を行えるため、 これを許可する必要はなくなりました。 加えて、これによりプリプロセッサとの衝突を避けられます。 (Issue 8662)
-
CSSOM が CSSStyleRule を CSSGroupingRule のサブクラスとして定義するようになったため、
cssRules属性と関連の仕組みについて手動で定義していた部分を削除しました。 (Issue 8940) -
特異性に対する(暗黙の)ネストセレクタの効果を明確化しました。 (Issue 9069)
-
規則と入り混じった宣言(またはネストされたグループ規則内のすべての宣言)は、 現在自動的に
ルールでラップされます。 (また@nest ルールが追加されました。) (Issue 8738)@nest -
を ネストされた宣言規則 に置き換えました。 (Issue 10234)@nest -
Web Platform Tests のカバレッジを追加しました。