みえのじゆうちょう

ゆるふわエンジニャー

CSSプロパティを深堀する話[z-index篇]

いやいやそんな話ググればありふれてるでしょって思いながらも。
仕様書読んだり色々調べて得た物をメモとして残そうって思いまして。

今回は、ウェッブが盛んになってきた頃には既にいた筈なのにCSS3が出て5年経過した今でもあまり理解されない感じがぷんぷんしてる子について今日はまとめてみようかなっていう。
私自身も使う機会が今までほんと少なかったのでゆるふわにしか把握してなかったので。改めて。

z-index

概要

  • Level2から追加された子
  • static以外のpositionプロパティが設定されている要素の重なり順を整数値で指定
  • [z]というのは3次元座標のアレです、xyz
    奥行きを示すz座標です。値が大きくなればなるほど手前にきます。

以上です。
という訳にもいかないので続けます。

スタッキングという概念のお話

要素に奥行きをもたせて重ねて行くことをスタッキングと言います。
スタッキングには決められた順序があるのですが、その前にスタックコンテキストスタックレベルについて

スタックコンテキスト

positionプロパティでstatic以外が指定され、z-indexにauto以外の値が設定された要素のこと。
スタックコンテキスト内のすべての子孫要素にそのスタックコンテキストを基準としてスタッキングの順番が割り当てられます。
子孫要素もまた、スタックコンテキストとなることができます。

スタックレベル

z-indexの値のこと。
z-indexは0を基準として-2147483647〜2147483647の値が設定できます。
z-index:autoのばあい、スタックレベルは0と見なされますが、スタックコンテキストにはなりません。

スタッキングの順番*1

  1. スタックコンテキストが整形する要素の背景とボーダー。
  2. 負のスタックレベルをもつ子スタックコンテキスト(最も小さな値が最初になる)。
  3. フロー内、非インラインレベル、非位置指定*2の子孫。
  4. 非位置指定の浮動体。
  5. インラインテーブルとインラインブロックを含む、フロー内、インラインレベル、非位置指定の子孫。
  6. スタックレベル0をもつ子孫。
  7. 正のスタックレベルをもつ子スタックコンテキスト(最も小さな値が最初になる)。

という基準にならって要素がスタッキングされます。
同じスタックコンテキストに存在し、スタックレベルが同じ要素は、HTMLで後に記述された物が上に配置されます。

まとめると

  • z-indexはpositionでtop/right/left/bottomと同様に重なりを変更できるプロパティ
  • なのでpositionはstatic以外を設定する必要がある
  • z-indexの値は大きければ大きいほど手前に来るよ
  • ただしそれは同スタックコンテキスト内でのルール
  • いくら999999999とか設定しても親スタックコンテキストのレベルが低ければ親兄弟要素のレベルは超えられません

See the Pen z-index sample by scaportolono (@scaportolono) on CodePen.

という感じ。

ですが
ちょっと困った奴らがいる訳です。

イレギュラーなスタックコンテキスト

以下の要素はz-indexをauto以外に指定しなくてもスタックレベル0のスタックコンテキストになります。

  • html要素(ルートスタックコンテキスト)
  • positionプロパティでstatic以外が設定された要素(位置指定要素)
  • opacityプロパティで1未満の値が設定された要素
  • transformプロパティでnone以外の値が設定された要素

イレギュラーとはいえ、上2つは何となく知ってる気がすると思います。
positionプロパティは、static以外を設定しないとz-index使えないということですし、
bodyにz-index設定してないにもかかわらずbody直下のdivがスタッキングできちゃったりするのはルートスタックコンテキストがいるからだったりするのです。

こんなところです。
ちょっとだけ引き出しの中身が増えました。
そこで新たに考えるのはz-indexの設計について。
twitterでもちびちび書いたんですが、画面IDのごとく10100とかって良策なのどうなのっていう。
いや私も他にいい案がひねり出せなくてこの手法で設計してるんですが。。
結局はドキュメントにちゃんと書き残そう;;ってことですよね。
仕様書大事。

気が向いたら別のプロパティも深堀します。
言うほど深くなかったケド。
お粗末様でした。

20160216:指摘いただき、イレギュラーなスタックコンテキスト最後2つ修正しました。

*1:W3C,CSS2:9.9.1より抜粋

*2:非位置指定:positionがstaticまたは設定なしの要素