-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Chrome 130でのCSSネスティング改善: CSSNestedDeclarationsの詳細 (#52)
* update * update * update * update
- Loading branch information
Yuto Yoshino
authored
Oct 14, 2024
1 parent
b47161b
commit 56549fa
Showing
1 changed file
with
131 additions
and
0 deletions.
There are no files selected for viewing
131 changes: 131 additions & 0 deletions
131
app/routes/posts/css-nesting-improves-with-cssnesteddeclarations.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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🛑になります。 | ||
|
||
<img src="https://github.com/user-attachments/assets/d2c31c61-c0fc-4584-a26f-ae813863db64"/> | ||
|
||
(左: 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) |