【iPhone対応】上スクロールで出現、下スクロールで隠すヘッダーを作る【jQuery】

こんにちは!フリーランスエンジニアののせっち@nosecchi01です。

下スクロール時はヘッダーを隠し、上スクロールで出現するヘッダーメニューの作り方のご紹介です。
通常の作り方なら沢山のブログ記事がありますが、iPhone(iOS)対応の記事はない印象でした。

よく見る書き方とその問題点とは?

よく見る書き方は下記です。

let startPos = 0;
let winScrollTop = 0;
const Header = $('#header');
$(window).on('scroll',function(){
  winScrollTop = $(this).scrollTop();
  if (winScrollTop >= startPos) {
    $(Header).addClass('is-hide');
  } else {
    $(Header).removeClass('is-hide');
  }
  startPos = winScrollTop;
});
.l-header {
  align-items: center;
  background: #fff;
  display: flex;
  height: 58px;
  width: 100%;
}
.l-header--fixed {
  left: 0;
  position: fixed;
  top: 0;
  transition: transform 0.3s;
  width: 100%;
  z-index: 999;
}
.l-header.is-hide {
  transform: translateY(-100%);
}

ほぼ他の記事からの引用ですので解説は省略します。

ですが、このままでは下記の問題が…。

iOSではページトップでヘッダーが隠れてしまう…

先ほど紹介したコードではiOSで致命的なバグが出ます。
ページ最上部に来たときにヘッダーが非表示になってしまいます。

原因は、iOSの仕様です。

iOSの仕様

  • 上スクロールでページ最上部に来ると、最後バウンスする。(最上部より更に上に行く感じ)
  • バウンスして戻ってくるときの挙動が下スクロール判定となる。
  • 結果、ページトップではヘッダーが非表示になってしまう。(最後スクロールダウンだから)

iOS対応のコードはこちら

条件を一つ書き足せばOKです。

let startPos = 0;
let winScrollTop = 0;
const Header = $('#header');
$(window).on('scroll',function(){
  winScrollTop = $(this).scrollTop();
  if (winScrollTop >= startPos && winScrollTop > 100) { // ここにコードを追加
    $(Header).addClass('is-hide');
  } else {
    $(Header).removeClass('is-hide');
  }
  startPos = winScrollTop;
});

winScrollTop > 100 を書き足しました。

  • StartPos: 直前までのスクロールの値
  • winScrollTop:現在のスクロール量

なので、現在のスクロール量が直前までのスクロール量より多い、かつ、現在のスクロール量が100スクロールより大きい場合、ということになります。

もっと簡単に言うと、

ページ最上部から100スクロール以内では、is-hideクラスを付けないよ、という条件を追加しました。
これで、iOSでのバウンスする問題を回避できます。

ほんの100スクロールですが、追従固定ヘッダーの状態になりますので、気になる方は100の値を調整してみてください。
UX的なデメリットはないし、あまりギリギリは狙わない方がいいと思い僕は100としました。

まとめ

  • よく見る上スクロールで表示、下スクロールで非表示のコードではiOSで不具合が出る。
  • iOS対応のためには条件を一つ追加すればOK!
  • iOSは意外と曲者です。

この記事を書いた人

のせっち

福岡県出身。早稲田大学卒。創業100年の鉄鋼商社でバンコク駐在最年少抜擢。毎日擦り切れるまで働かなくても幸せに生きている人々を見てフリーランスになりました。
現在は、主にバンコクでWeb制作、物販を中心に生きています。