Panda Noir

JavaScript の限界を究めるブログでした。最近は幅広めに書いてます。

z-indexを心穏やかに使うための方針

z-indexを「なんとなく」で扱っていませんか?その結果

  • すべてのCSSを読まないと重なりについて理解できない
  • 最大値を探し出さないとつぎの要素を設定できない
  • z-index:100と設定する

といったことになったこと、ありませんか?z-indexという"""災厄"""とうまく付き合いたくありませんか?

ポイント: z-indexを「グローバル」に扱わない

z-indexを使っていて混乱するのは「グローバルに」扱ってしまっているからです。グローバル変数が悪というのは古から言われています。z-indexもグローバルに扱うことはもちろん握手です。

z-indexを「ローカルに」領域を区切って扱えると良いと思いませんか?実はできるんです!

z-indexは重ね合わせコンテキスト内で比較される

z-indexには「重ね合わせコンテキスト」という概念があります。z-indexの値は同じコンテキストのなかで比較されて、重なりが決まります。つまり、重なりあいを決めたい要素を同じコンテキストに入れて、そのコンテキスト内でのz-indexのみ検討すればいいことになります。

重ね合わせコンテキストの条件

重ね合わせコンテキストを使えばz-indexをローカルに使えることがわかりました。では、どのようなとき重ね合わせコンテキストが生まれるのでしょうか?

MDNには重ね合わせコンテキストになる条件はたくさんあるように書いてあります。しかし、覚える必要はありません。短く要約すると「重なる可能性がある要素」「重なったときに特殊な考慮が必要そうな要素」に対して重ね合わせコンテキストが生成されます

たとえば

  • positionがabsoluteの要素は移動するかもしれない
  • fixedやstickyも重なるかもしれない
  • opacityの要素があると重なりを考慮しなければならない

こういった具合に、他の要素と重なる可能性がある場合にコンテキストが生成されます。

ローカルにz-indexを決めよう

重ね合わせコンテキストは階層構造にできます。

ルートコンテキスト
    - コンテキストA
        - コンテキストA-1
        - コンテキストA-2
    - コンテキストB
        - コンテキストB-1
        - コンテキストB-2
    - コンテキストC
        - コンテキストC-1
        - コンテキストC-2

z-indexは、おなじ重ね合わせコンテキストにいる要素間で比べられるので、兄弟コンテキストの子要素については考える必要がありません。図にするとこんな感じです。

f:id:panda_noir:20190126230253p:plain

コンテキストBのなかにz-indexが100の要素がありますが、z-indexが3の要素に負けています。これはz-index:100の要素が、コンテキストAの兄弟コンテキストBに属するためです。立体的にするとこうなります。

f:id:panda_noir:20190127003148p:plain

「コンテキストBがコンテキストAの下」だから「コンテキストBに属するz-index100はコンテキストAの下」となります。

z-indexは「同階層でのみ」使用する

z-indexを異なる階層の要素を比較するときに使おうとするため、ややこしいことになってしまっているので、異なる階層のものと比べるというのはやめましょう。ほとんどの場合、異なる階層の要素を比較しなくて済むはずですので。

同階層での比較なので、z-indexを100に設定したりする必要もほぼなくなると思います。

参考

z-index再入門 - z-indexの仕組み | CodeGrid

z-index | MDN

重ね合わせコンテキスト | MDN