
こんにちは、yutaです。
タイトルが少し挑発的でしたね、ゴメンナチャイ。
ところで今回は、Webページを作っている人ならぶつかった事のあるであろう、もしくは知らんふりしているであろうz-indexの謎についてお話しします。
キーワードは、「スタックコンテキスト」です。スタック文脈とか重ね合わせコンテキストなどとも呼ばれています。なんじゃそりゃ。
まずは、Webページってこんな感じだよねというところから。
Webページって、3次元なんです。笑(は?何言ってんだコラァ)
Webページをみる時に私たちが使っているディスプレイは平面なので、2次元な空間(xy平面)しか意識していませんよね。
だから下図の様に[div A][div B]という要素を記述すると、記述された順に縦に並んで行きます。(y軸方向に並んでいく。)

しかし、実際にはWebページは3次元でできているので、z-index(z軸の値)を指定することで[div C]の様にz=1のレイヤーに要素を配置することができます。

同様にして、z-index:2とすれば[div D]の様にz=2のレイヤーに要素を配置できます。

これをディスプレイ、つまりxy平面で見た場合下図の様になりますね。
この様にして、z-indexを指定するとこで任意のレイヤーに要素を配置して、要素間での重なりを表現できるのです!

では・・・z-indexが大きければ大きいほど要素は手前に表示されるのか?
・・・正しい。
・・・正しい、けど甘いッッ!!笑
正確には、「同じスタックコンテキスト上の要素はz-indexが大きいほど手前に表示される」です。
はい、でました、スタックコンテキスト。
僕個人的には、「スタックコンテキスト=3次元空間」と考えるのが分かりやすい様な気がします。つまり最初に示した図、もう一度↓に出しますが、これもスタックコンテキストです。
このx,y,z軸でできている3次元空間、これ自体がスタックコンテキスト。
ならば、スタックコンテキスト=3次元空間。なるほど、わからん。

問題は、ある条件下でスタックコンテキスト(3次元空間)が生成される(増える)という点です。
スタックコンテキストが生成される条件は色々あり詳細はこちらの記事を見て欲しいのですが、今回はその代表的な条件を1つ挙げて説明します。
ずばり、スタックコンテキストが生成される条件は・・・
「position:relativeもしくはabsolute」かつ「z-index:0もしくはauto以外」の時。
・・・ん?よく分からん。という方はとりあえず「z-indexを指定した時」にスタックコンテキスト(3次元空間)が生成されると考えてください。
ということはですよ、↑の方でz-index:1とか2で配置していた[div C]や[div D]にはスタックコンテキストが生成されるということなんです。言葉じゃ分かりにくいので下図を見てください。

上図を見ると分かりますが、z-index:1に配置された[div C]を起点として新たにスタックコンテキスト(3次元空間)が生成されています。z-index:2に配置した[div D]の方にも別のスタックコンテキストが生成されていますね。
この様にして現在3つのスタックコンテキスト(3次元空間)が存在していることになります。
おっ・・・?勘の良い方は気づいたからもしれませんが、[div C]や[div D]の中に配置する要素にz-indexを付ける場合、その値はそれぞれのスタックコンテキスト(3次元空間)のz軸に対する値になります。
例えば下図の様に[div C]の中に要素(星)を含め、それをz-index:100で配置したとします。するとこれは、[div C]を起点としてできているスタックコンテキスト(3次元空間)のz軸での値になります。
よって、この要素(星)に与えられたz-indexは大元のスタックコンテキスト(下図の一番大きな3次元空間)や、[div D]を起点としてできたスタックコンテキストのz-indexとは全く関係の無い値となります。
スタックコンテキスト同士で、z-indexの干渉というものはありませんので、[div C]の子要素にz-index:100としても[div D]の子要素より手前に表示されることはありません。(たとえ、[div D]の子要素のz-indexが0であってもです。)
[div C]を起点に生成されたスタックコンテキストは、大元のスタックコンテキスト上でのz-indexが1です。(下図をみて確認してくださいね。)
[div D]を起点に生成されたスタックコンテキストは、大元のスタックコンテキスト上でのz-indexが2です。(下図をみて確認してくださいね。)
したがって、そもそも[div D]を起点に生成されたスタックコンテキストは、[div C]を起点に生成されたスタックコンテキストよりも上位のレイヤーになるので、[div C]の子要素に対してどれだけ大きなz-indexを与えようが[div D]を突き抜けて手前に出てくることは無いのです。

したがって、上図の要素(星)はz-index:100にも関わらず、z-index:2の[div D]を突き抜けて手前に表示される様なことにはならないのです。

実際には、下図の様になりますね。

さきほども言いましたが、スタックコンテキスト間での干渉は無いので、たとえ[div D]に子要素を作ってマイナスのz-index(z-index:-100とか。)を与えたとしても[div C]の子要素(上図の星とか。)より奥側に表示されること(見えなくなること)はありません。何度も言ってますが、[div D]を起点としたスタックコンテストはそもそも[div C]を起点としたスタックコンテキストより上位のレイヤーだからですね。
僕自身もz-indexを良く使ってるのにもかかわらず、「スタックコンテキストって聞いたことあるけど良く分からん。」状態だったので調べて自分なりにまとめてみました。
本記事の途中で紹介したこちらの記事に加え、こちらも非常に参考になりました。
ブログランキングに参加しています。この記事が参考になったという方は、僕のモチベーション維持のためにもバナーをポチッとお願いします!笑
