CSS の z-index について整理してみる
目次
今日は CSS Nite in Ginza, Vol.31に行ってきます。テーマは「CSSレイアウト:IE 6対応のかんどころ/小林 信次(まぼろし)」ということで、以前「CSS Nite ビギナーズに参加した感想とか要望とか」で書いた「CSS Nite への要望っぽいこと」が実現した感じで、すごく楽しみです。
僕は Web制作の現場にいないので、実務経験が少ないです。ですので、日頃、Web 制作を仕事としてやっている人が、サッと解決できちゃうようなことにもハマったりします。
そういった点を補うには、今日の CSS nite のようなテーマはすごくありがたいです。
さて、前置きが長くなりましたが、今日は以前ひっかかった IE6 の z-index の解釈について、改めて整理してみました。
どんなシーンでハマったか
このブログもそうですが、最近ページ上部にグローバルナビゲーションを配置し、それを jQuery の superfish などを使って、スルスルっと表示させるレイアウトをやることが多いです。
このとき、スルスルっとさせたときのメニューが、IE6 だと隠れちゃったりするのです。
z-index について
ます、最初に CSS の z-index について「z-index CSS 表示と配置 | World Wide Web Guide」を参考に復習しておきましょう。
z-indexプロパティの指定がない場合、及び z-indexプロパティに "auto" が指定されている場合の位置要素されている要素の重なり方は、文書のソース内であとに記述されている要素ほど上に重ねられて前面に表示されることになります。また、位置要素されている要素と、位置指定されていない要素(position : static ; が指定された要素、及び positionプロパティの指定されていない要素)とでは、位置指定された要素が上に重なって前面に表示されることになります。そこで、z-indexプロパティは重ね合わせの順番が上手くいかないときに、ソース内で要素が記述されている位置に関係なく、要素の重ね合わせる順序を調整することができます。
サンプルのソース
上記の z-index の性質を踏まえて、以下のようなソースで実験してみます。CSS も HTML 内に書いちゃっています。
実用的なイメージとしては、div#header の中に z-index を適用するグローバルナビゲーション(ここでは div#floating)がある場面を想定しています。
IE6 のバグかな?
header div. header div. header div. header div. header div. header div. header div. header div. header div. header div.
floating box. floating box. floating box. floating box. floating box. floating box.
primary div. primary div. primary div. primary div. primary div. primary div. primary div. primary div. primary div. primary div.
secondary div. secondary div. secondary div. secondary div. secondary div. secondary div. secondary div. secondary div. secondary div. secondary div.
これを IE6 で表示すると次のようになります。Firefox でも同様です。
先ほどの z-index の説明からも、position: static; 以外で位置指定されている要素(#header、#floating)と、位置指定されていない要素(#contents)とでは、位置指定された要素が上に重なって前面に表示されているので正しい表示です。
ソース内で後に記述された要素に position 設定を加えるとおかしくなる
ここで、上記の CSS の位置に関わる部分を次のように変更してみます。
/* 以下の設定が影響 */
#header { position: relative;}
#floating { position: absolute; z-index: 10;}
#contents { position: relative;}
すると、Firefox では表示は変わりませんが、IE6 では z-index: 10; が設定されている div#floating が div#contents と重なっている部分が隠れてしまいます。
本来 position: static; 以外の要素は、後から記述された要素が前面になるところを、「z-index によって記述の順序に関係なく、要素の重なりを調整することができる」はずなので、これはおかしいです。
もし、#floating に z-index: 10; が設定されていなければ、Firefox でも上の画像のようになります。
対処方法
IE6 でこの状態を回避するには、次のように #header に z-index: 1; を加えればOKです。
#header { position: relative; z-index: 1;}
#floating { position: absolute; z-index: 10;}
#contents { position: relative;}
つまり、IE6 の場合、position: static; 以外の要素が入れ子になっている場合、子要素に z-index を指定しても正常に反映されず、「親要素の重なりの順序が優先」されるようです。
試しに、CSS を次のように変更してみるとどうでしょうか。
#header { position: relative; z-index: 1;}
#floating { position: absolute; z-index: 10;}
#contents { position: relative; z-index: 1;}
この場合、Firefox でも IE6 でも次のような表示になります。
つまり、Firefox でも IE6 でも、いくら子要素の z-index の値を大きくしても、隣接する親要素の両方に z-index が設定されていると、その親要素同士の重なり順序が優先されるようです。
続いて、次のように後に記述された親要素のみに z-index が指定されているとどうなるでしょうか。
#header { position: relative;}
#floating { position: absolute; z-index: 10;}
#contents { position: relative; z-index: 1;}
この場合、Firefox では z-index の値が優先され、IE6 では親要素同士の重なり順序が優先されるようです。
[ Firefox の場合]
[ IE6 の場合]
まとめ
これらをまとめると、CSS の z-index プロパティは、ブラウザによって次のように扱われるようです。
[ Firefox の場合]
- 仕様で定められている通り。
- 隣接する親要素の両方に z-index が設定されている場合は、子要素の z-index よりも隣接する親要素の重なり順序が優先する。
- それ以外の場合は、z-index の値が優先する。
細かくはチェックしていませんが、おおむね他のモダンブラウザも同様でした。
[ IE6 の場合]
- 隣接する親要素の重なり順序が優先する。
以上です。