iPhoneでページ下部のタップイベントを確実に発火する方法

スマホ用に見やすく設定されたWEBページのパターンの1つに画面下に固定されたナビゲーションがあります。ユーザーの親指の位置に近いので良いデザインかと思いきやiPhoneで落とし穴があるので注意が必要です。

iPhoneでページ下部固定メニューをタップしても一回では動かない問題

iOSの標準ブラウザsafariで下に表示されるステータスバーが非表示の時はその表示エリアのタップイベントがブロックされる仕様になっています。さらにiPhoneX、iPhone11は今までと画面の形が違うのでセーフエリアというものが存在します。これもも含めてタップイベントがブロックされます。

解決方法(ブラウザハック風)

CSSでイベントブロック箇所を避けて配置されるように指定します。

  1. viewportにviewport-fit=coverを加える
   <meta name="viewport" content="initial-scale=1, viewport-fit=cover" />

これを加えることで後述の「safe-area-inset-*」が使えるようになります。

  1. css変数「safe-area-inset-*」を使用して位置を調整する
  .selector {
    position: fixed;
    left: 0;
    bottom: calc(env(safe-area-inset-bottom) + 44px);
  }

safe-area-inset-*はiPhoneX、11用の値になります。
env()はセーフエリアの大きさを取得するための関数です。
つまりbottom値は「下のセーフエリア分の高さ+ステータスバーが隠れているデッドゾーンの高さ44px」という事になります。
「calc使ってたらIE11で効かないじゃん」と一瞬思いますがスマホ前提なので問題ありません。

更に詳しくは以下の記事がとてもわかりやすく書いてあります。
CSSだけでiphoneの特殊な画面に対応する方法と、XcodeとXAMPPを使って実際に確認する方法|Webデザインの教科書

解決方法(ステータスバーを隠さない)

CSS変数で対応する方がスマートですがviewportがいじれなかったり、CSSを位置をずらしたくない場合は無理やりステータスバーを常時表示することで確実にタップイベントを発火させることができます。

<body>
  <div id="body">
    <p>コンテンツ</p>
  </div>
</body>
#body {
  height: 100vh;
  overflow: scroll;
  /* -webkit-overflow-scrolling: touch; @XXX 不要になりました */
}

※なぜ「-webkit-overflow-scrolling」が不用になったか?

これはiOS5~13のsafariだけのプロパティになります。もともとページ全体のスクロールはスムーズでしたが要素内のスクロールは以前は現在のようにスムーズではありませんでした。そのため要素内のスクロールはこのプロパティをつけることでスムーズに惰性スクロールを再現できました。現在はこのプロパティがなくても十分スムーズにスクロールされるように端末(ブラウザ?)が改良されているのでなくても問題ないようです。

ステータスバーはやっかいなのでじっくり対応しましょう

今回だと解決法1の方がスマートで好きですが、デザインを変更しなくてよいので2の方が使用頻度は高いかもしれません。一番良いのはメニューを画面下部に置かないことですね。ブラウザの機能を阻害することは避けたいものです。