Interactive

スタッキングコンテキスト可視化

z-index: 9999を付けたのに前に出ない——その理由は数値ではなくスタッキングコンテキストの入れ子にあります。重なり順の解決タブでは要素のCSSを編集すると、 生成条件の判定・7段のペイント順・2要素がどのコンテキストのどの段で決着したかが更新されます。 プレビューは模式図ではなく同じCSSを当てた本物のDOMなので、 計算した順序とブラウザの描画をその場で見比べられます。

シナリオ

祖先の opacity:0.99 が新しいコンテキストを生み、その内側の 9999 は親の順位という天井を超えられない。記事の最頻パターン。

ブラウザによる実描画

下の枠は模式図ではなく、同じCSSを当てた本物のDOMです。 計算した順序とブラウザの描画が一致するかを、その場で目視できます。

.card(opacity:0.99)
.modal(z-index:9999)
.header(z-index:10)
比較する2要素

.header(z-index:10)が手前 /.modal(z-index:9999)が奥

段7(正のz-indexの子コンテキスト)が段6(z-indexが0/autoのポジション要素・子コンテキスト)より手前に塗られるため決着。z-indexの数値は見ていない。 比較しているのは要素自身ではなく、それぞれが閉じ込められている子コンテキストの根同士——ここが「z-indexを盛っても前に出ない」の正体。

決着したコンテキスト

html(root)

決め手

7段のどの段か

実際に比べた相手

.header(z-index:10)
.card(opacity:0.99)

ペイント順(奥 → 手前)

1html(root)1コンテキスト生成要素自身の背景・ボーダー
2.card(opacity:0.99)1コンテキスト生成要素自身の背景・ボーダー
3.modal(z-index:9999)1コンテキスト生成要素自身の背景・ボーダー
4.header(z-index:10)1コンテキスト生成要素自身の背景・ボーダー

コンテキストを生成する要素は、自分のコンテキストの段1(自身の背景・ボーダー)として現れ、 その部分木がまるごと続きます。だから外から見ると1つの塊として動きます。

要素を編集する

スタッキングコンテキストを生成する

  • position: absolute かつ z-index: 9999(auto以外)

ペイントされる段: 7正のz-indexの子コンテキストz-index: 9999(正)→ 段7

position: absolute なので z-index が段の選択に効く

判定はCSS 2.1のペイント順と各仕様の生成条件に沿った実装です。position: fixedは transformを持つ祖先が無いとビューポート基準になるため、プレビュー内では枠の外へ出ることがあります(それ自体が記事の指摘する挙動です)。

ここが分かる

  • 祖先のopacity: 0.99ひとつで天井ができる——見た目はほぼ変わらないのに新しいコンテキストが生まれ、内側のz-index: 9999は親の順位を超えられない。opacityを1に戻した瞬間に順位が逆転するのを確認できる。
  • 比較しているのは要素同士ではないことがある——別コンテキストに閉じ込められている場合、実際に比べられるのは「それぞれを閉じ込めた子コンテキストの根」同士。可視化はその実際の比較相手を名指しで示す。
  • z-index: auto0はペイント段が同じで生成有無だけが違う——見かけの重なりは変わらないのに、0にした途端に子孫のz-indexが外へ漏れなくなる。「0にしたら子の重なりが変わった」の正体。
  • 負のz-indexは親の背景の上・内容の下——段2は段1(親の背景)より手前だが段3(通常フローの内容)より奥。「-1にしたら文字の後ろに回った」が段の並びから読める。
  • 通常フローのブロックは段3固定でz-indexを持てない——positionもtransformも無い要素は、いくら大きな値を書いても無視される。段の表示がその場で「効かない」と告げる。