z-indexで躓いてしまうこと

今回はz-indexで思い悩んでしまうことについて取り上げてみます。


この記事を書く前までz-indexを指定した値の大きな要素ほど前面に配置されると思っていました。


しかしこれは間違いでした。。。
z-indexのことを知らなすぎました。


それでは何を知らなかったのか、どのような局面で自分は躓いたのかを説明していきます。




html

<div class="white">
  <div class="red"></div>
</div>


css

.white {
  position:relative;
  z-index:1;
  width:60px;
  height:60px;
  background:#fff;
  border:solid 1px #000;
}

.red {
  position:absolute;
  top:10px;
  left:20px;
  z-index:-1;
  width:60px;
  height:60px;
  background:red;
  border:solid 1px #000;
}


あれれ、思った通りの場所に配置されないな汗
.whiteの方がz-indexの値が大きいから前面にくるでしょ?
と、結構思い悩みました。。


z-indexは値の大きさだけで要素が前面に配置されるわけではないのです!
z-indexプロパティは、positionプロパティの初期値(static)以外の値が指定されている要素には、自動的にautoが適用された状態になります。
要するに今回の場合、.redのpositionがabsoluteと指定されているので親要素である.whiteと同じz-index:auto;が自動的に指定されるのです。
しかしこれだけでは.whiteと.redのz-indexの値は同じだけであって何故.redが前面に配置されるかわかりませんよね。。


では他に何か要因があるのでしょうか??


スタック文脈スタックレベルというものが関係している模様!



まずスタック文脈です。


スタック文脈は階層構造のことをいいます。

・ルート要素(HTML)
・位置指定されていて、z-index 値がauto以外の要素
・z-index 値が "auto" 以外の flex アイテム
・1 未満の opacity 値を持つ要素(不透明度の仕様をご覧ください)
・transform 値が "none" 以外の要素
・mix-blend-mode 値が "normal" 以外の要素


上記のようなスタック文脈を形成する条件を満たした要素は、自身を基準としたローカルスタック文脈を形成します。
スタック文脈を形成しない要素はその親のスタック文脈に内包されることになります。



次にスタックレベルは、同一のスタック文脈内での重なり順です。z-indexの値が、同一スタック文脈内でのスタックレベルになります。同じスタック文脈内に、同じスタックレベルの要素がある場合、その構造内でより後方にある要素が前面に配置されます。


少し例を挙げてみたいと思います。


blue
red
yellow
green
black


html

<div class="white_box">
  <div class="blue"></div>//z-index:5;
  <div class="red"></div>//z-index:3;
  <div class="yellow">//z-index:4;
    <div class="green"></div>//z-index:10;
    <div class="black"></div>//z-index:7;
  </div>
</div>


css

.white_box {
  position:relative;
  width:800px;
  height:300px;
}

.blue {
  position:relative;
  top:50px;
  z-index:5;
  width:500px;
  height:200px;
  background:rgba(0, 0, 255, 0.7);
  color:#fff;
}

.red {
  position:absolute;
  top:100px;
  left:50px;
  z-index:4;
  width:500px;
  height:200px;
  background:red;
  color:#fff;
}

.yellow{
  position:absolute;
  top:30px;
  left:100px;
  z-index:3;
  width:300px;
  height:100px;
  background:rgba(255, 255, 0, 0.8);
  color:#fff;
}

.green {
  position:absolute;
  top:40px;
  left:200px;
  z-index:10;
  width:250px;
  height:80px;
  background:green;
  color:#fff;
}

.black {
  position:absolute;
  top:70px;
  left:100px;
  z-index:7;
  width:150px;
  height:80px;
  background:black;
  color:#fff;
}


まず黒色のボーダーで囲まれた箱の中に色がついた箱が合計5個あり、その箱すべてにz-indexの値をつけました。
これらはスタック文脈が形成されています。
blue,yellow,redの箱は同一のスタック文脈の中にあるのでスタックレベルで前面か、後方に配置されるかが決まります。
z-indexの値が大きいほど前面に配置されます。
z-indexが定められていない要素が複数ある場合は下に記述した要素の方が前面に表示されます。


そして注目してほしいのはyellowの中にある要素.greenと.backです。
どちらも.blue,redの箱よりもz-indexの値が大きいにも関わらずblueより前面に配置されません。


これは先ほど説明した通りスタック文脈の中にある要素はそのスタック文脈の外にでることができません
したがって.blueやredの箱よりも後方に配置されるのです。



このようにz-indexを扱う上ではスタック文脈、スタックレベルまたpositionの知識が必要とされます。
知らなかった人は実践してもう一度確かめてください!!