Chrome 130でのCSSネスティング改善: CSSNestedDeclarationsの詳細
- publishedAt:
- 2024/10/13
- updatedAt:
- 2024/10/14
目次
Intro
web.devが先日、CSS nesting improves with CSSNestedDeclarationsというブログを公開しました。
このブログでは、CSSネスティングの仕様にCSSNestedDeclarations
が追加されたことについて書かれています。果たして業務でこのブログで書かれてるようなような動きに出くわすことはなかった気もしますが、CSSOMの動きなど少し面白かったので書くことにしました。
話さないこと
この記事では以下の内容については書きません。
- CSS nestingとは
- CSSのparse処理について
CSSネスティングの以前までの仕様
まずCSSネスティングの以前までの仕様についてです。 以下のようなCSSを書いた場合、皆さんはどのようなUIになると思いますか??
.foo {
width: fit-content;
@media screen and (min-width: 900px) {
background-color: red;
}
background-color: green;
}
関連: github.com/yossydev/css-nesting-improves-with-cssnesteddeclarations
この場合、適用されるbackground-colorはred🛑になります。
(左: Chrome129 / 右: Chrome130)
しかし、CSSの仕様としては後ろに書かれたコードが適用されるはずです。これがChrome 129までのCSSネスティングの仕様でした。
なぜこのような仕様だったのか
なぜこのような仕様になっていたのでしょうか?
Intent to Ship: The Nested Declarations Ruleというやり取りの中には、以下のように記載されています。
This was at the time done intentionally for a mix of CSSOM and historical reasons, and all implementations of CSS Nesting currently agree on this behavior. However, it turns out this shifting behavior isn’t what authors expect (WebKit blog post), and the CSSWG now consider the decision a mistake. In October 2023, the CSSWG resolved to not do the shifting behavior anymore
要約すると以下のようになります。
- CSSOMの歴史的背景から、Shifting(入れ替わり)されるような挙動で実装を行った
- しかし作者(authorsの直訳、多分私たちのような開発者のことを指していると思う...??)が想定していた動きと異なっていた
- そしてCSSWGがこのShiftingするような仕様をmistakeだとした
実装した時点ではその方針で進んでいたけど、それを使用する開発者にとっては思っていた挙動と違ったので直すことにした。ということらしいです。
どのようにShitingされるのか
では次に、実際にどのようにShitingされるのをみてみましょう。 先ほどのCSSに対して生成されたCSSOMを例にします。
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.resolvedSelectorText = ".foo"
.specificity = (0,1,0)
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: green
.cssRules (CSSRuleList, 1) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(.foo)"
.specificity = (0,1,0)
.style (CSSStyleDeclaration, 1) =
- background-color: red
background-color: green
はCSSStyleRule.style
に含まれているものの、@media screen
の後に定義されたかどうかはわからないです。そのため、パースされたCSSをみると、以下のようになります。(出力された結果から見やすくなるように少し整形しています)
.foo {
width: fit-content;
background-color: green;
@media screen and (min-width: 900px) {
background-color: red;
}
}
この結果、background-color: green
が@media screen
よりも上に来てしまいました。これではCSSの優先順位的に、min-width: 900px
が正の時はredが適用されます。
(そもそも常にbackground-color: green
にしたいならbackground-color: red
いらないのでは?みたいなご意見はごもっともです)
CSSNestedDeclarationsの追加
CSS Working GroupはShiftingを解消するために、新しくnested declarations ruleを追加しました。
同じCSSの内容に対して、Chrome130からは以下のようなデータ構造になります。
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.resolvedSelectorText = ".foo"
.specificity = (0,1,0)
.style (CSSStyleDeclaration, 1) =
- width: fit-content
.cssRules (CSSRuleList, 2) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSNestedDeclarations
.style (CSSStyleDeclaration, 1) =
- background-color: red
↳ CSSNestedDeclarations
.style (CSSStyleDeclaration, 1) =
- background-color: green
今度はCSSNestedDeclarations
というものが追加されているのがわかるかと思います。
これにより、パーサーは以前の宣言の位置を維持させることができるようになりました。
@nest
今回CSSNestedDeclarations
が追加されましたが、最初の提案では@nest
というものが提案されていたようでした。(CSS Nesting: @nest)
そしてこの提案に関して、Webkit側が拒否しています。
WebKit strongly opposes introducing an @nest rule for this purpose. We don't think expanding the syntax space of CSS for the convenience of CSSOM representation is an acceptable cost to authors, and prefer a solution that represents interleaved style declarations in the CSSOM in a way that does not have an externality on CSS syntax. ref: https://github.com/WebKit/standards-positions/issues/337#issuecomment-2078329470
CSSOMのために名前空間を拡張するのは好ましくなく、CSSの構文に影響を与えないように、CSSOMのインターフェースを拡張することが理想とのことです。 あまりここは本題と逸れるので、このくらいにしておきます。
まとめ
今回はChrome130で追加されるCSSNestedDeclarations
について、導入背景と一緒に見ていきました。
CSSのパースについて、正直今まで考えて開発をしてこなかったので、今回の内容で興味を持つきっかけになりました。特に今回はあまり触れられていないのですが、nested declarations ruleの具体的な実装内容みたいなところも、時間があれば読んでみたいと思います。
追記・編集
いくつか今回の内容でフィードバックいただいたので、内容の修正を加えています。
- 10/14: バグという表現が適切ではなかっため、CSSの仕様であるという言葉の使い方に修正しました。
- 10/14: CSSのshitingの問題について追記しました。
ご指摘ありがとうございました🙇♂️
参考・関連
0