その使い方合ってる?z-indexで指定した筈の重なり方にならない時に気をつけたいこと

こんにちは、ユアサです。
以前業務で要素同士の重なり方について、自分ではうまく思ったようにコーディングできなかったことがありました。z-indexプロパティを使ったはいいものの、なぜかそのスタイルが反映されず一体何が原因なのやら・・・・。
個人的に意外とややこしいプロパティだと感じたのもあり、今回は自分の備忘録も兼ねてz-indexが効く場合と効かない場合についてまとめます。

z-indexを使うにあたっての前提条件

この記事を読んでくださっている方には説明は必要ないかもしれませんが、z-indexは言わずと知れた要素同士の重ね順を指定するプロパティです。これは指定された数値が大きい要素が小さい要素より上に重なります。
またz-indexは単体では機能せず、値がstatic以外のpositionプロパティも一緒に指定する必要があります。(relativeでもabsoluteでもfixedでも可)
コーディング初歩の方はこのpositionの指定がなくてz-indexが機能しないということがよくあるので、まずここを疑ってみてください。
簡単なものですが、実際に組んでみると以下のようになります。

See the Pen Untitled by felly (@felly00505) on CodePen.

親要素がparent、その各子要素をそれぞれchild1とchild2という名前にしています。z-indexを指定しないと重ね順は上からchild2→child1→parentとなりますが、child1にのみz-index: 10;と指定しているのでchild1が重ね順の一番上に来ているのが確認できます。
またz-indexで指定された値は基本的に兄弟要素(同じ親要素に入っている子要素同士)である場合か親要素とその中の子要素の場合で判定される仕様なので、例えば他の親要素に入っている子要素同士(例:親要素Aに入っている子要素A-1と親要素Bに入っている子要素B-1)といった場合では機能しません。

親要素を子要素の上に重ねる(子要素を親要素の下に表示させる)

同じ親要素内に入っている子要素同士でz-indexの判定が行われることは分かりました。では子要素を親要素より下に表示させる(あるいは親要素を子要素の上に重ねる)ができるのかというと可能です。例えば子要素の一つにz-index: -10;と指定した場合、その子要素は親要素より下に表示させることができます。
しかし一部例外があります。下記のコードをご覧ください。

See the Pen z-index2 by felly (@felly00505) on CodePen.

子要素のchild1にz-index: -10;を指定していますが、なぜか親要素より上に表示されています。これは親要素parentにz-indexを指定しているためで、これが負数でも自然数であっても指定されている限り子要素を親要素の下に表示させることができません。
なぜそんなよく分からないことが起きるんだ・・・・各z-indexの値を子要素は負数にして親要素は自然数にしたら数値自体は問題ないじゃないか・・・・と思うかもしれませんが、これには原因がありました。
親要素と子要素にはz-indexを指定していない状態では、指定はされていませんがz-indexが初期値のautoになっています。z-index: auto;は親要素と同階層にいると判定されるものであるため、親要素にz-indexを指定せず子要素にのみ指定した場合にそれが親要素も判定される対象になるので、子要素に負数の値のz-indexを指定すると親要素より下に表示されるという仕組みです。
しかしその状態で親要素にz-indexを指定すると、「z-index: ○○;の親要素の中にあるz-index: -××;の子要素」という関係が成立してしまうので、あくまでも兄弟要素のみでの判定になってしまいます。親要素のz-indexの値にも気が抜けませんね・・・・。

他要素とのより細かい重なり具合の指定について

全パターン挙げたらキリがないので一例に留めますが、例えば親要素AとBがあり、Aの子要素にA-1とA-2、Bの子要素にB-1というものがあるとします。
兄弟要素でのルールは分かったけれど、では子要素のA-1と親要素Bという入れ子関係ですらない要素同士のような重なり方は指定できるかというと、できないこともないです。
下記のコードをご覧ください。

See the Pen z-index2 by felly (@felly00505) on CodePen.

これは「親要素Aの中の子要素A-1をAの下に表示させるが、AとA-1の間にBが挟まれているように表示させる」といったパターンです。(このパターン自体はそう使うようなものでもありませんが・・・)
別々の親要素に入っている子要素同士ではz-indexは機能しませんが、子要素と別の親要素とでは機能する場合があります。何が起きているのかを順を追って説明します。
A内でz-indexが指定されているのはA-1のみなので、A-1はAより下に表示させることができています。次にBにA-1よりも大きい且つ負数になるようなz-indexの値を指定すると、結果的にz-indexが初期値状態のAと値が指定されている要素のA-1・Bのみでの判定となるため、重ね順は上からA-2→A→B-1→B→A-1となります。
しかり仮にこれのAにz-index: -1000;など指定されていたら、A-1のz-indexは想定していたように機能せずBもAの上に重なってしまうといったことが起こります。このように、この場合でも親要素のz-indexの値によって重なり方はかなり変わってくるので、こちらもうまく再現できない時はまず親要素や入れ子関係を見直していくと原因究明が比較的早くなるかと思います。

まとめ

今回はz-indexの重なり方について具体的な例を挙げて、効く場合と効かない場合の紹介をしました。
コーポレートサイトなどでは基本何重にもz-indexで要素を重ねることはまず無いので大丈夫かと思いますが、最近YouTubeなど動画配信サイトでCSSだけでスタイリッシュなデザインを作成する動画が少しずつ増えていっているようで、もしかしたらビジュアルに重きを置くページなんかではこのz-indexを多用する機会も出てくるのかなと感じています。
今回も最後まで読んでいただきありがとうございました(^人^)