タイトルの元ネタになっている『BLEACH』は読んだことありません。
悩ましいz-index問題
CSSを学んだことある人なら一度は通るz-index
問題。単純にz-index
の値で重なりが決まるのではなく、親要素との関係によって重なりが変わるので複雑です。ついz-index: 9999
はやってしまいます。(一番上なんだな、っていうのが分かりやすいので良いとは思いますが)
これが問題になるのはposition
のプロパティを使ったときが多いですが、position
以外にもz-indexが有効になるプロパティがあります。
具体例がこちら↓
See the Pen
z-index by Nishihara (@Nishihara)
on CodePen.
この記事ではHTMLは以下のようにid
の小さい方から書かれている前提になります。
<sectionclass="section section1"><divid="block1">z-index: 3</div><divid="block2">z-index: 2</div><divid="block3">z-index: 1</div></section>
display: flexの時
display: flex
を使った際の子要素も実はz-index
が有効になります。flexだけを使って重ねるというのは、あまりない場面かもしれませんが、ネガティブマージンを使って重ねるとz-index
が効いているのが分かります。
.section1{display:flex;justify-content:flex-start;}#block1{background-color:rgb(228,100,100);z-index:3;}#block2{background-color:rgb(100,228,100);z-index:2;margin-top:40px;margin-left:-80px;}#block3{background-color:rgb(100,100,228);z-index:1;margin-top:80px;margin-left:-80px;}
display: gridも
flexと同様にdisplay: grid
でもz-index
が使えます。そもそもgrid
でレイアウトを重ねることは少ないと思いますが。。。
.section2{display:grid;justify-content:flex-start;grid-template:"block1 block2 block3"120px/120px120px120px;}#block4{background-color:rgb(228,100,100);z-index:3;}#block5{background-color:rgb(100,228,100);z-index:2;margin-top:40px;margin-left:-80px;}#block6{background-color:rgb(100,100,228);z-index:1;margin-top:80px;margin-left:-160px;}
組み合わせても有効になる
これらも要素にz-index
が有効であることを知らなくても、それぞれを単体で使う場合にはそんなに問題はありません。問題になってくるのは、position
やこれらを組み合わせた時です。
例えば下記のように、flexで並べて、子要素にposition: absolute
を使って配置し、transform: translate
で重ねた場合はどうでしょう?その場合もz-index
の値が効いてきます。
.section3{display:flex;position:relative;justify-content:flex-start;}#block7{background-color:rgb(228,100,100);z-index:3;}#block8{background-color:rgb(100,228,100);z-index:2;position:absolute;top:40px;left:40px;}#block9{background-color:rgb(100,100,228);z-index:1;transform:translate(-40px,80px);}
この場合は、#block7
が一番上にきます。
z-indexパズル
z-index
を指定しない場合は重ね合わせコンテキストのルールに従って、HTMLで後に書かれているものが上になります。では、次のような場合どうでしょう。
.section4{display:flex;position:relative;justify-content:flex-start;}#block10{background-color:rgb(228,100,100);}#block11{background-color:rgb(100,228,100);position:relative;margin-top:40px;margin-left:-80px;}#block12{background-color:rgb(100,100,228);margin-top:80px;margin-left:-80px;}
子要素にはz-index
が指定されていません。なのでHTMLで一番最後の要素の#block12
が一番上に来そうですが、実はそうではありません。
よく見ると、#block11
にはposition: relative
が指定されています。そうすると、新たに重ね合わせコンテキストが発生するので#block11
が一番上にきます。しかしここに、
#block10{background-color:rgb(228,100,100);z-index:1;}
とz-index
を指定すると通常の重ね合わせコンテキストを上書きするように#block10
が一番上に来ます。ここまでくるとz-indexパズルですね!
transform?
Firefoxだけ、要素にtransform
のプロパティを使った時もz-index
が有効になります。
#block13{background-color:rgb(228,100,100);transform:translate(0,0);z-index:3;}#block14{background-color:rgb(100,228,100);transform:translate(40px,-80px);z-index:2;}#block15{background-color:rgb(100,100,228);transform:translate(80px,-160px);z-index:1;}
では、transform: translate3d(x,y,z)
でz方向に奥行きに移動させたらz-index
の位置関係が変わるのでしょうか?
結論から言うと変わりません。transform
のz軸方向とz-index
のレイヤーは別ものなので重なりが入れ替わるようなことはありません。
transform
を使って重ねるときにはブラウザで差が出てくるので要注意です。
最後に
重ね合わせがうまく行かなかったら、これらz-index
が有効なプロパティも疑ってみてください。それでもダメな場合は重ね合わせコンテキストを考慮してみてください。