下にスクロールすると隠れて上にスクロールしたら登場するヘッダJS(とCSS)

この記事は最終更新日から8年以上経過しています。

今作っているサイトでヘッダの動きをタイトルのようにしたくなったので調べてみたんだけど、既にあるライブラリは細かい挙動がどれも思っているのと微妙に違ったので結局自分で書く事にした。

デモ

欲しかった細かい挙動はこんなの

  1. コンテンツを閲覧中、上にスクロールするとヘッダが上からニュッと登場する
  2. 再度下にスクロールすると上にアニメーションして消える
  3. ページの一番上からスクロールしはじめた時は、ヘッダはアニメーションで隠れるのではなく、 ページ上部に普通に配置されたまま、スクロールする要素の1つとして消えていく (medium.comやiOSのSafariのような挙動)
  4. 動きとしては これ が一番理想に近いんだけど、スマホではjQueryのslideUp, slideDownを使っているので動きが気持ち悪かった。 cssのアニメーションで動かしたい
  5. scroll-up-barはiOS用のバッドノウハウが入っているけどそれももういらならそう
  6. スクロールイベントは頻繁に発火して重いので Underscore.js のthrottleなどを使用して無駄に何度も実行されないようにしたい

3と4追加したかったがために、ちょっとjsがややこしくなってしまった。 実装の中身は

  • jsからはクラスの追加、削除を行うのみ
コピーしました
var element = '.js-followheader';
var lastY = 0;
var minY = $(element).height();
$(window).on('scroll', _.throttle(updateScroll, 100));

function updateScroll(e) {
  var y = $(window).scrollTop();
  if (y < lastY) {
    plugin.scrollUp(y);
  } else if (y > lastY) {
    plugin.scrollDown(y);
  }
  lastY = $(window).scrollTop();
}

function scrollUp(y) {
  $(element).removeClass('is-close');
  if (y > minY) {
    if(!$(element).hasClass('is-open')) {
      $(element).addClass('is-open');
    }
  } else if(y <= 0){
    $(element).removeClass('is-open');
  }
}

function scrollDown(y) {
  if (y > minY) {
    if($(element).hasClass('is-open')) {
      $(element).removeClass('is-open');
      $(element).addClass('is-close');
    }
  }
}
  • アニメーションやヘッダの高さの設定などはcssで記載
コピーしました
.followheader
  $h: 50px
  @keyframes enter
    from
      top: -$h
    to
      top: 0px

  @keyframes leave
    from
      top: 0px
    to
      top: -$h

  position: absolute
  top: 0
  left: 0
  width: 100%
  z-index: 999
  height: $h
  &.is-open
    position: fixed
    animation: enter 0.3s ease-out
    top: 0
  &.is-close
    position: fixed
    animation: leave 0.3s ease-out
    top: -$h

というような感じで作っている。

ソースコードはあんまり綺麗じゃないけど こちら に上がっています。 リポジトリの方は記事と違って使い回しできるようにjQueryプラグインになってます。

Profile

石原 悠 / Yu Ishihara

デザインとプログラミングと編み物とヨーグルトが好きです。