Web production note

 【更新日 :

【脱Jquery】JavaScriptで上スクロール時に表示される追従ヘッダーを実装する

Category:
JavaScript

JavaScriptで追従ヘッダーを実装したサンプルです。
上スクロールもしくは、ページ最下部に到達すると表示されます。
表示はディレイ時間(0.5秒)を設けているので、一瞬上にスクロールしたら即表示されるような挙動も防止しています。

codepen

See the Pen Fix Header Vanilla JS (scroll up to show) by web_nak (@web_walking_nak) on CodePen.

HTML

<header id="global-header" class="global-header">
  <p>追従ヘッダー(上方向にスクロールすると表示)</p>
</header>

CSS

transitionはお好みで設定してください。

.global-header {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  --transition: transform .6s cubic-bezier(.19,1,.22,1);
}
.global-header.is-fix {
  position: fixed;
  transform: translate3d(0,-100%,0);
}
.global-header.is-hide {
  transform: translate3d(0,-100%,0);
  transition: var(--transition);
}
.global-header.is-show {
  transition: var(--transition);
  transform: translate3d(0,0,0);
}

JavaScript

表示するまでのディレイ時間(showDelay)の変更や対象class名や変更したい場合は、初期設定のoptionsを編集してください。

//ヘッダー追従関数(上スクロール時、ページ最下部到達時のみ表示)
function headerScrollFunc() {
  'use strict';

  //追従ヘッダー取得
  const header = document.getElementById('global-header');

  //初期設定
  const options = {
    fixClass: 'is-fix',  //追従class
    hideClass: 'is-hide',  //追従中 非表示class
    showClass: 'is-show',  //追従中 表示class
    showDelay: 500 //表示するまでのディレイ時間(指定秒数(ミリ秒)以上、下スクロールしなければ表示)
  };

  //ヘッダーが存在するかチェック
  if(!header) {
    return false;
  }

  //スクロール開始位置
  options.startPosi = 0;
  //上スクロール判別フラグ
  options.upFlg = false;
  //表示タイマー用設定
  options.setTimeoutFlg = false;
  options.setTimeoutId = 0;


  //ヘッダーfix関数呼び出し
  window.addEventListener('resize', function() {
    headerFix(options);
  });
  window.addEventListener('scroll', function() {
    headerFix(options);
  });

  //追従設定
  function headerFix(options) {
    //追従前のヘッダー位置(ヘッダーの位置によって色々パターンがあると思います)
    const headerBasePosi = 0;

    /*
      ヘッダーを追従させる位置
        画面の高さ、特定の要素の位置から追従開始など、色々パターンがあると思います。
        今回はヘッダーの高さを超えたら追従処理を開始
    */
    const headerFixPosi = header.clientHeight;

    //スクロール量(ウィンドウの上端)取得
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;

    //class設定
    const fixClass = options.fixClass;
    const showClass =options.showClass;
    const hideClass =options.hideClass;

    //上下スクロール判別
    //下スクロール(新規取得したスクロール量がoptions.startPosiを超えている)
    if (scrollTop > options.startPosi) {
      //上スクロール判別フラグを無効化
      options.upFlg = false;

      //表示タイマーリセット
      clearTimeout(options.setTimeoutId);
      options.setTimeoutFlg = false;

      //スクロール量がヘッダーを追従させる位置を超えているか
      if(scrollTop > headerFixPosi) {
        //追従class追加
        header.classList.add(fixClass);
      }

      //ページの高さ取得
      const pageHeight = document.documentElement.scrollHeight;
      //下スクロール位置取得
      const scrollBottom = window.innerHeight + scrollTop;
      //ページの最下部だった場合はヘッダーを表示
      if (pageHeight <= scrollBottom) {
        headerShow(hideClass,showClass);

      //ページの途中だった場合
      } else {
        //表示されている場合ヘッダーを非表示
        if(header.classList.contains(showClass)) {
          headerHide(hideClass,showClass);
        }
      }


    //上スクロール(新規取得したスクロール量がoptions.startPosi以下)
    } else {
      //上スクロール判別フラグを有効化
      options.upFlg = true;

      //ヘッダーが追従前の位置に来ている場合は追従を終了する
      if(scrollTop <= headerBasePosi) {
        //全ての追従用classを削除
        header.classList.remove(fixClass,showClass,hideClass);

      //ヘッダーが追従前の位置を超えている場合
      } else {
        //表示タイマーが設定されていなければタイマーを設定
        if(!options.setTimeoutFlg) {
          //表示タイマーセット
          options.setTimeoutFlg = true;
          //指定秒数以上、下スクロールしていない場合のみヘッダーを表示
          options.setTimeoutId = setTimeout(function() {
            if(options.upFlg && header.classList.contains(fixClass)) {
              headerShow(hideClass,showClass);
            }
          }, options.showDelay);
        }
      }
    }

    //スクロール開始位置を更新
    options.startPosi = scrollTop;
  }

  //追従ヘッダー表示関数
  function headerShow(hideClass,showClass) {
    header.classList.remove(hideClass);
    header.classList.add(showClass);
  }

  //追従ヘッダー非表示関数
  function headerHide(hideClass,showClass) {
    header.classList.remove(showClass);
    header.classList.add(hideClass);
  }
}

関数の呼び出し

任意の場所で以下を実行し関数を呼び出してください。

//ヘッダー追従関数呼び出し
headerScrollFunc();