ブラウザの表示領域に対して要素の位置を固定してくれるposition: fixed;
は、表示領域が限られるスマートフォンでこそ使いどころがたくさんあるのだが、(特にAndroidで)バグが多くて実用にはまだまだ慎重にならざるを得ない。
今回は、iOSで遭遇したバグについて記述しておく。
#症状
position: fixed
を指定した要素がz-index
を無視する。
精確に説明すると、position: fixed
を指定した要素が、表示領域外にある部分が、スクロールされて表示領域に入ってきたときに、スクロールされている間だけ、z-index
が無視されて、より大きなz-index
が指定されている(即ちより手前の)要素より前面に表示される。
実際のコードをご覧いただこう。
<div class="contents">ここに通常のコンテンツ</div>
<div class="bg"></div><!-- 背景表示のための要素 -->
<div class="footer">
iPhoneだと通常スクロールしなければ見えない要素
</div>
.contents {
position: relative;
z-index: 10;
height: 500px;
}
.bg {
position: fixed;
z-index: 1;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background-image: url(bg.jpg);
}
.footer {
position: relative;
z-index: 10;
height: 200px;
background-color: #fff;
}
div.footer
は、スクロールしなければ見えない位置にある。
スクロールすると見えるはずなのだが、なぜかdiv.bg
の下に隠れて見えないのだ。そしてこの現象が発生するのは、 スクロールしている間だけ であり、スクロールが停止した段階で、前面に正しく表示される。
また、div.footer
がスクロール前に表示領域内に一部でも見えていれば、この現象は発生しない。
現象を確認した環境
- iOS7 Safari, Chrome
- iOS6 Safari, Chrome
iOS版 Operaではこの現象は見られなかった。
position:fixed
を使った理由
なぜ、div.contents
にbackground
を設定するのではなく、div.bg
という要素をわざわざ用意しているかというと、背景画像をスクロールさせずに固定位置に配置したかったからである。
背景画像を固定にするためのプロパティbackground-attachment: fixed
は、スマートフォンではうまく機能しないケースが多いため、このようなハックが出回っているが、そのために別のバグにでくわしたというわけだ。
#対応策
下に隠れてしまうdiv.footer
に以下のcssを指定することで解消される。
.footer {
-webkit-transform: translate3d(0,0,0);
}
ただし、translate3d
を設定することによって、Androidでは全く別のバグを誘発しうるので注意を要する。
必要に応じて、JavaScriptでユーザーエージェントで判定してclass属性を出し分けるなどして、このCSS記述がiOSのときだけ反映されるように工夫してやる。
position:fixed
くらい、そろそろ普通に使いたい。background-attachement:fixed
も。