【CSS/JavaScript】「iPhone iOS 背景固定 background-attachment:fixed ツールバー メニューバー 下 余白」でお困りの方へ

スマホだと background-attachment:fixed が使えないので、背景画像を固定する時に「::before」で代用するコードを良く見かけますね。

ただ、このあたりのコードをそのまま利用すると、iOSでスクロールする際に「メニューが隠れたり表示されたり」切り替わるタイミングで、下に変な余白ができてしまったり、background-size: cover; を設定しているとガクガクになったりします…。

結論としては、以下にすればOKです。

<script>
    (function () {
        //iOSのときのみ処理追加
        if(isiPhone()) $('#fixed').css({height: screen.height});
    })();
</script>
<style>
    #fixed {
      display: block;
      position: fixed;
      background: url(/img/bg_feature_summer.png) 50% 100% no-repeat;
      background-size: cover;
      top: 0;
      left: 0;
      width: 100%;
      height: 120%;
      -webkit-transform: translate(0, 0);
      transform: translate(0, 0);
      z-index: -1;
    }
</style>
<div id="fixed"></div>

transform を設定しないともスクロール中に変な余白が発生します。これを記載すると「描画をGPUが行うため解決できる」とのことで、おまじないのようなものです(笑)

これでも 「メニューが隠れたり表示されたり」 するタイミング(=リサイズ)で画面の高さが変わるため、height: 100%; と記載するだけでは下に余白が発生します。そのため height: 120% を設定しています。

ただ、リサイズのタイミングで背景画像がガクガクしちゃいます。仕方ないので、JSで予め screen.height で高さを指定しておくと違和感なくなりました。しかし、AndroidやiPad含めタブレット端末は、viewportの設定等の理由で devicePixelRatio の値が適切に取得できず、heightの設定が困難なので、取り急ぎiPhoneのみ対応しています。

追記:iPhoneのiOS11だと「もっと見る」後、imgタグが表示されない?

上記実装後、アコーディオンメニューのような「ボタンをタップしたあと中身を表示する」場合、iOS11のiPhoneだとコンテンツ内のimgタグがなぜか表示されません。

以下の状況が近いのかなと思います。

こちらの環境ではiPadでは再現せず、iPhoneのみの問題でした。取り急ぎの処置として、開いた後に一旦#fixedを非表示にし、すぐ再表示することで対応できました。

<style>
    #moreArea {
        display:none;
    }
</style>

<div id="fixed"></div>
<div id="moreArea">
    <img src="/img/img.png">
</div>
<button id="moreBotton">もっと見る</button>

<script>
$('#moreBotton').on('click', function () {
    $('#moreArea').show();
   //なぜかmoreArea内のimg.pngが表示されないので対応(iPhoneのみ)
   if(isiPhone()) {
       $('#fixed').hide();
       setTimeout(function () { $('#fixed').show(); }, 10);
   }
});
</script>