CSS大解剖 10日目: 「レイアウトループ」
本稿は、2024年2月頃に書き溜めていたシリーズです。最後まで温存させるのが勿体ないので、未完成ですがそのまま公開します(公開日: 2025/9/24)。そのため、内容の重複や記述方針の不一致があるかもしれませんが、ご理解ください。
CSSの仕様を理解するために、1日ごとにテーマを決めて説明する企画10日目です。今日のテーマは「レイアウトループ」です。
本稿の目的
CSSはスタイルに対する意図をなるべく宣言的に書けるようにしていますが、これは実質的に制約プログラミングであると言えます。たとえば、
min-width: 300px;
と書けば、これはcontent boxのsizeが300px以上であるという制約を宣言したものとみることができます。
理想的な制約プログラミングでは、しばしば矛盾する制約が生じたり (overconstrained)、制約が少なすぎて解がひとつに決まらなかったり (underconstrained)、また仮に解が一意に存在していたとしてもアルゴリズム的に簡単には見つけられないなどの問題が生じます。
CSSはそこまで厳密に制約を解きたいわけではありません。なので、実際には制約の解決順序が定められていて、その順序で決定論的に解いたものと同等の答えが返せればいいというような仕組みであるとみなすのが妥当です。
本稿は、このような立場から制約の依存関係を明らかにし、CSSを素朴な手続きとして理解する手助けをすることを意図しています。あくまで仕様上の解の決定手段を検討しているだけなので、実際のWebブラウザに求められる高速なアルゴリズムを記述しようとしているわけではないので注意してください。
カスケード — レイアウト ループ
「カスケード — レイアウト ループ」はQuery Containerをサポートするために必要だと考えられる最上位ループです。Query ContainerはWorking DraftであるCSS Containment Module Level 3で定義されています。
旧来のCSSでは、レイアウトを行わずに全てのボックスのcomputed valueを算出することができるように設計されていました。しかしQuery Containerとなっている要素以下のスタイルを算出するにはQuery Containerの条件判定を行う必要があり、この条件を判定するにはその祖先要素のレイアウトを部分的または完全に決定する必要があります。
この相互依存は、要素のツリー構造に沿った再帰処理があると解釈することで解消可能です。それをここでは「カスケード — レイアウト ループ」と呼ぶことにします。
レイアウトの最上位ステップ
「カスケード — レイアウト ループ」の各回は以下のようなステップからなると考えられます。
- 対象部分木内の要素のカスケードを計算する。
- 対象部分木内のボックスツリーを生成する。
- 対象部分木内の匿名ボックスのカスケードを計算する。
- 回り込みボックスの処理を行い、ボックスツリーを変形する。
- 対象部分木のボックスツリーから、レイアウト文脈のなす木を抽出する。
- レイアウト文脈のなす木に対して再帰的にレイアウトを行う。
Discussion