背景画像を固定して中のコンテンツだけをスクロールさせるページを作成していたところ、スマートフォンでは「background-attachment:fixed;」が効かないことに気付きました。
スマートフォンでも背景画像を固定させたかったので、「background-attachment:fixed;」と同様の挙動をさせるための代替手順を試したらうまくいったので、ご紹介したいと思います。
スマートフォンで背景画像を固定させる方法(CSSによる対処)
PCの「background-attachment:fixed;」と同様に、スマートフォンでも背景画像を固定させるためには、CSSで以下のように指定します。
body::before { content: ""; background: url(img/bg-sp.png) no-repeat center center; background-size: cover; display: block; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: -1; transform: translateZ(0); }
bodyに::before疑似要素で背景画像を指定しています。
これで、背景全体に固定した画像を設置できます。
Twitterにて、TAKさんから「transform:translateZ(0);」を追加すると、スクロール時のチラつきを抑えることができるとご指摘いただいたので追記しました。
ちなみにサンプルには記載されていませんが、固定背景用の要素に僕はtransform:translateZ(0);を指定しています。transformとしては意味の無いプロパティですが、これを指定することでGPUレイヤーを生成することが可能で、スクロールした時のチラつきを抑えることができます(割と重要なテクニック)
— TAK (@tak_dcxi) August 13, 2019
iPhoneやiPadでうまくいかない場合(jQueryによる対処)
iPhoneやiPadでは、背景の高さ計算のバグがあるようで、背景画像の大きさが異様に大きく表示されてしまったり、逆に小さく表示されてしまうことがあります。
上記の方法ではiPhoneやiPadでうまくいかないという場合は、jQueryを使って対処する方法もあります。
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script> $(function() { var height = $(window).height(); var device = navigator.userAgent; if (device.indexOf('iPhone') !== -1 || device.indexOf('iPad') !== -1) { $("body").css({ "background-size": "auto " + height + "px" }); } }); </script>
「device.indexOf(‘iPhone’) !== -1 || device.indexOf(‘iPad’) !== -1」で、”iPhoneかiPadの場合”という条件を指定しているため、上記スクリプトはiPhoneかiPadでアクセスした場合のみ実行されます。
jQueryによってデバイスの高さを取得して、bodyのbackground-sizeに固定値(px)を指定するようにしています。background-sizeの高さを固定値にすることで、背景画像の大きさがおかしくなるのを防ぐことができます。
CSSでは、前述したような::before疑似要素を使う必要はなく、bodyに背景画像を指定してあげればOKです。
あとがき
スマホで「background-attachment:fixed;」が効かないとは知りませんでした。勉強不足ですね…
上記の代替案が使えるので、同じように固定背景を実装したい時は、ぜひ参考にしていただければと思います。
なぜかうまくいかなくて困っていました。お陰様で解決できました!