From 56549fae2137691380e82341781a60e7a10ba478 Mon Sep 17 00:00:00 2001 From: Yuto Yoshino Date: Mon, 14 Oct 2024 11:52:33 +0900 Subject: [PATCH] =?UTF-8?q?Chrome=20130=E3=81=A7=E3=81=AECSS=E3=83=8D?= =?UTF-8?q?=E3=82=B9=E3=83=86=E3=82=A3=E3=83=B3=E3=82=B0=E6=94=B9=E5=96=84?= =?UTF-8?q?:=20CSSNestedDeclarations=E3=81=AE=E8=A9=B3=E7=B4=B0=20(#52)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update * update --- ...ng-improves-with-cssnesteddeclarations.mdx | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 app/routes/posts/css-nesting-improves-with-cssnesteddeclarations.mdx diff --git a/app/routes/posts/css-nesting-improves-with-cssnesteddeclarations.mdx b/app/routes/posts/css-nesting-improves-with-cssnesteddeclarations.mdx new file mode 100644 index 0000000..b0308cb --- /dev/null +++ b/app/routes/posts/css-nesting-improves-with-cssnesteddeclarations.mdx @@ -0,0 +1,131 @@ +--- +title: "Chrome 130でのCSSネスティング改善: CSSNestedDeclarationsの詳細" +description: "web.devが先日、CSS nesting improves with CSSNestedDeclarationsというブログを公開しました。このブログでは、CSSネスティングの仕様にCSSNestedDeclarationsが追加されたことについて書かれています。導入背景やCSSOMの動きなどが少し面白かったのでブログにまとめました。" +date: "2024/10/13" +published: true +--- + +## Intro + +[web.dev](https://web.dev/?hl=en)が先日、[CSS nesting improves with CSSNestedDeclarations](https://web.dev/blog/css-nesting-cssnesteddeclarations?hl=en)というブログを公開しました。 + +このブログでは、CSSネスティングの仕様に`CSSNestedDeclarations`が追加されたことについて書かれています。果たして業務でこのブログで書かれてるバグに出くわすことはなかった気もしますが、CSSOMの動きなど少し面白かったので書くことにしました。 + +## 話さないこと + +この記事では以下の内容については書きません。 + +- CSS nestingとは +- CSSのparse処理について + +## CSSネスティングでの既存のバグ + +まず既存のCSSネスティングであったバグについてです。 +以下のようなCSSを書いた場合、皆さんはどのようなUIになると思いますか?? + +```css +.foo { + width: fit-content; + + @media screen and (min-width: 900px) { + background-color: red; + } + + background-color: green; +} +``` + +関連: [github.com/yossydev/css-nesting-improves-with-cssnesteddeclarations](https://github.com/yossydev/css-nesting-improves-with-cssnesteddeclarations) + +この場合、適用されるbackground-colorはred🛑になります。 + + + +(左: Chrome129 / 右: Chrome130) + +しかし、CSSの仕様としては後ろに書かれたコードが適用されるはずです。これがChrome 129までのCSSネスティングに関するバグでした。 + +## なぜこのようなバグが存在するのか + +なぜこのようなバグが存在していたのでしょうか? +それは、CSSOMを使ったパース処理が関係しています。 + +先ほどの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は新しく[nested declarations rule](https://drafts.csswg.org/css-nesting/#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`というものが追加されているのがわかるかと思います。 +これにより、パーサーは以前の宣言の位置を維持させることができるようになりました。 + +## まとめ + +今回はChrome130で追加される`CSSNestedDeclarations`について、導入背景と一緒に見ていきました。 +CSSのパースについて、正直今まで考えて開発をしてこなかったので、今回の内容で興味を持つきっかけになりました。特に今回はあまり触れられていないのですが、[nested declarations rule](https://drafts.csswg.org/css-nesting/#nested-declarations-rule)の具体的な実装内容みたいなところも、時間があれば読んでみたいと思います。 + +## 参考・関連 + +- [CSS nesting improves with CSSNestedDeclarations](https://web.dev/blog/css-nesting-cssnesteddeclarations?hl=en) +- [nested declarations rule](https://drafts.csswg.org/css-nesting/#nested-declarations-rule)