Skip to main content

Module paint_order

Module paint_order 

Source
Expand description

描画順(スタッキング順)の算出。

§背景 — 実際に踏んだバグ

描画側は全要素を z_index でフラットにソートしていた。ところが実サイトの CSS には

section { position: relative; z-index: 5 }

があり、<section class="hero" id="home"> は z=5、その子孫 (.hero-overlay / .hero-content / .hero-title)は position: static なので z=0 だった。 フラットソートでは セクションが自分の子孫より後に描かれ、自分の背景で 自分の中身を丸ごと消してしまう。実測でも、ヒーローテキストは描画直後に 1655px 残っているのに draw() 終了時点で 0 になっていた。

§仕様(CSS 2.1 Appendix E)

スタッキングコンテキストを作る要素は、自分の背景を先に描き、子孫はその コンテキストの中で描かれる。子孫が祖先の背景より前に描かれることは無い。

§実装方針

各要素の「実効 z」を max(自分の z, 祖先の実効 z) とする。 文書順では祖先が必ず子孫より先に現れるため、実効 z が同値なら安定ソートが 祖先→子孫の順を保つ。これで祖先の背景が子孫を塗り潰す事故は起きない。 子孫が自前でより大きい z-index を持つ場合はその値が勝ち、祖先より後= 手前に描かれる(これも仕様どおり)。

グローバル状態にもハードウェアにも依存しない純粋ロジックのみで構成する。

Enums§

PaintOrderError
実効 z の算出でおかしな入力を検出した場合のエラー。

Constants§

MAX_DEPTH
祖先チェーンの深さ上限。これを超えるツリーは異常とみなす。

Functions§

effective_z
要素の実効 z を求める。
effective_z_from_chain
祖先チェーン(ルート→親の順)から実効 z を求める。
paint_cmp
2 要素の描画順の比較(Less が先=奥)。path は祖先のスタッキングコンテキストの段の列。
paint_sort_key
描画ソートキー。(実効 z, 位置指定層, ツリー深さ) の昇順で並べる。
stack_step
要素自身の段。seq はその要素を生んだ箱の文書順(箱が要素列へ積み始めた位置)で、 祖先の箱の seq は子孫の箱の seq 以下になる。同値(祖先が子孫より後に積まれた場合)は 深さの浅い方が先(I-1)。深さを第 1 にしていた平坦版と違い、別の部分木どうしは文書順で並ぶ。

Type Aliases§

StackStep
入れ子のスタッキングコンテキストの 1 段((z, 位置指定層, 文書順, 深さ))。 要素の描画キーは「祖先のコンテキストの段の列 + 自分の段」。