タイトルの元ネタになっている『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
の小さい方から書かれている前提になります。
<section class="section section1">
<div id="block1">z-index: 3</div>
<div id="block2">z-index: 2</div>
<div id="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 /
120px 120px 120px;
}
#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パズルですね!
最後に
重ね合わせがうまく行かなかったら、これらz-index
が有効なプロパティも疑ってみてください。より詳しいスタッキングコンテキストとz-indexの関係は『君は真に理解しているか?z-indexとスタッキングコンテキストの関係』もご参照ください。