z-index
を使って要素の重なりを制御するとき、何も考えずに適当に z-index: 100;
などと指定したりしていませんか? このあたりの仕組みをよく理解せずに z-index
を濫用していると、いつか怪奇現象に見舞われてつらいことになるかもしれません。
怪奇現象の例
早速ですが、以下のコードを御覧ください。
<div class='boxes'>
<div class='box1'>
.box1 { z-index: 1 }
</div>
<div class='box2'>
.box2 { z-index: 2 }
<div class='box3'>
.box3 { z-index: 0 }
</div>
</div>
</div>
.boxes {
color: white;
position: relative;
}
.boxes div {
width: 10em;
height: 10em;
position: absolute;
}
.box1 {
background-color: red;
top: 0;
left: 0;
z-index: 1;
}
.box2 {
background-color: green;
top: 3em;
left: 3em;
z-index: 2;
}
.box3 {
background-color: blue;
top: 3em;
left: 3em;
z-index: 0;
}
これをブラウザで開くとどのように表示されるでしょうか?
z-index
の値を見た感じでは、 box2 > box1 > box3 の順番で重なって表示されそうですね。
しかしこれは以下のように表示されます。
z-index
が一番小さいはずの box3 が最前面に表示されています。これは何故でしょうか。
スタックコンテキスト
CSS には**スタックコンテキスト(スタック文脈)**という概念があります。
スタックコンテキストは、ある特定の要素をベースとした子孫要素の集合です。
html 要素は初期状態でルートスタックコンテキストを生成しているため、すべての要素は何らかのスタックコンテキストに所属しています。
スタックコンテキストを生成しうる「ある特定の要素」は、いくつかあるのですがひとつだけ挙げると
- 「
position
がstatic
以外」かつ「z-index
がauto
以外」である要素
です。
要するに、「z-index
を有効にした要素はスタックコンテキストを生成する」ということです。
上記の例で言うと、box1, box2, box3 はすべてスタックコンテキストを生成しています。
[2022.06 追記]
isolation
を使ってスタックコンテキストを生成することもできるらしいです。
https://developer.mozilla.org/ja/docs/Web/CSS/isolation
z-index とスタックコンテキスト
z-index
の値はスタックレベルと言い、要素の重なる順番を表すプロパティですが、実はこれは所属するスタックコンテキスト内での順番を指定するものです。
class | z-index | スタックコンテキスト | 重なり順のイメージ |
---|---|---|---|
.box1 | 1 | html (root) | root > 1 |
.box2 | 2 | html (root) | root > 2 |
.box3 | 0 | .box2 | root > 2 > 0 |
.box3
のスタックレベルは 0 ですが、 .box3
は .box2
のスタックコンテキストに所属しているため、.box2
のスタックコンテキストに所属している要素集合の中でのスタックレベルが 0 である、ということです。
そのため、最終的な重なり順は box3 > box2 > box1 となるわけです。
まとめ
z-index
の値が同じでもスタックコンテキストによって重なり順序が変わることがあるので、スタックコンテキストを意識してスタイルを書いていけると良さげ ₍₍⁽⁽(ી( ・◡・ )ʃ)₎₎⁾⁾