仕事で z-index プロパティを使う機会があったんですが、なんだか上手くいかなかった。いろいろ試行錯誤してようやく思い通りの動きをしてくれたので、ここに z-index プロパティの仕様を含めたまとめを書いてみる。
まずは z-index プロパティの仕様から。引用するのが面倒なので仕様書をそのまま見てください。
簡単に仕様をまとめると、
- position プロパティで [fixed] [absolute] [relative] のいずれかの値を持つ要素(つまり [static] 以外の値)にのみ適用される
- z-index プロパティの [auto] はボックスの重なり順が親要素と同じになる
- [整数] は値が大きいほど値が小さいボックスよりも前面になり、小さいほど大きい値よりも背面に配置される
- [整数] はマイナスの値も指定できる
以上のようになる。
これを踏まえたうえで以下のサンプルを作成してみる。
HTML ソース
<div id="zindex2">
z-index の値が 2<br />
要素の順番は 1
</div>
<div id="zindex1">
z-index の値が 1<br />
要素の順番は 2
</div>
<div id="zindex0">
z-index の値が 0<br />
要素の順番は 3
</div>
CSS ソース
div#zindex0 {
position: absolute;
top: 50px;
left: 180px;
z-index: 0;
width: 200px;
height: 200px;
background: yellow;
}
div#zindex1 {
position: absolute;
top: 80px;
left: 210px;
z-index: 1;
width: 200px;
height: 200px;
background: pink;
}
div#zindex2 {
position: absolute;
top: 110px;
left: 240px;
z-index: 2;
width: 200px;
height: 200px;
background: lime;
}
想定できる結果です。z-index プロパティの値が大きくなるほど前面に配置される。仕様通りの結果です。
では次にこうしたらどうなるだろうか。
HTML ソース
<div id="zindex2">
z-index の値が 2<br />
要素の順番は 1
<div id="zindex1">
z-index の値が 1<br />
要素の順番は 2
<div id="zindex0">
z-index の値が 0<br />
要素の順番は 3
</div>
</div>
</div>
つまり各要素を入れ子にしてしまう場合。そうすると先ほどとは表示結果が違うことが分かる。これは単純な話で、position プロパティが [absolute] の時、基点がサンプル 1 とサンプル 2 では違うからだ。
position CSS辞典 - position - 要素の配置方式を指定する
- absolute
- 包含ブロック(祖先要素のうち、もっとも近い祖先の要素にあたるブロック要素の内容領域)の各辺を基準に配置され、"top, bottom, left, right" の各プロパティで指定する絶対的な位置指定となる(祖先要素に位置指定されている要素がなければ、初期包含ブロックを基準とする)。
"absolute" の説明を補足しておくと、たとえば、一番最初の包含ブロックである初期包含ブロックは、html要素の各辺が基準になるので、スクロール分も含めてページ全体が基準になります。つまり、topプロパティ・leftプロパティはページの左上が原点に、bottomプロパティ・rightプロパティはページの右下が原点となります。html要素に対して、widthプロパティ, heightプロパティを指定することで、初期包含ブロックの横幅・高さを指定することもできます。
上記の通り、id="zindex2" は最上位の基準となる先祖要素が無いため、初期包含ブロック(html 要素)を基準に配置されている。
id="zindex1" は id="zindex2" に包含されているため、id="zindex2" を基準として配置し、同様に id="zindex0" は id="zindex1" を基準に配置されている。
しかし問題はここではない。id="zindex1" と id="zindex0" が重なり合っている点が重要である。
通常であれば id="zindex0" の上に id="zindex1" が重なるはずだが、実際は逆に id="zindex1" の上に id="zindex0" が重なっている。
要素を入れ子にしたら z-index プロパティの挙動がおかしくなったと考えられる。しかしこれは恐らく仕様通りの結果のはずです。
z-index プロパティの仕様は以下のようになっています。
- 'z-index'
値: auto | <integer> | inherit 初期値: auto 適用対象: 位置決め要素 継承: しない パーセント値: N/A メディア: 視覚メディア
仕様では z-index プロパティは継承されません。ですので、子孫要素が新たな z-index プロパティを指定しても、それが親要素を継承していないため、例え値が 0 であったとしても親要素の背面に配置されることはないのです。
つまりここでは、id="zindex1" の値が 10 であったとしても、子要素の id="zindex0" からすると値は id="zindex1" は 0 に見えるのです。
なので、対応策としては id="zindex0" の値をマイナス値にしてしまえば解決します。
div#zindex0 {
position: absolute;
top: 50px;
left: 180px;
z-index: -1;
width: 200px;
height: 200px;
background: yellow;
}
しかし何故か IE6 と Opera9 ではダメなんですが・・・仕事でやった時は上手くいったんですけどね。ちょっと事情が違うみたいなので、今度また再検証してみます。
以下独り言(何
なんとなく position プロパティが怪しい感じ。仕事でやった時は[absolute] と [relative] の組み合わせだったから、なんかその辺が絡んでるのかも。
と思って試してみたが、やっぱ違うっぽい。そもそもの考え方が違うのかなぁ。ほぼ同じような構成で再度検証してみるしかないかも。
