jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5

Tips

jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5

一度は見かけたことがあると思う、スクロールしたらヘッダーやナビゲーションを固定表示させたり見栄えを変化させたりする動きをjQueryで実装するサンプルです。
途中から要素を固定させたり、スクロールした方向によって表示・非表示を切り替えたりなど全5種類です。

※プレフィックスは必要に応じて追記してください。

※以下で紹介している方法はいずれもjQueryを使用していますので、あらかじめ読み込ませてください。

※適用させる要素やclass名などの各変数については、自身の環境にあわせて変更してください。

使用するHTML

特にこのようにしなければいけないというものではないですが、今回のサンプルで使用しているHTMLはいずれも下記のようなもの(サンプルによってはnav要素がないものもあります)になっており、このHTMLにあるheadernav要素に対してjQueryで処理していくといった感じになります。

HTML

<header>
  ...
</header>

<nav>
  ...
</nav>

<main>
  ...
</main>

<footer>
  ...
</footer>

jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5 目次

  1. ナビゲーションが途中から固定
  2. 下にスクロールでヘッダー非表示・上にスクロールでヘッダー表示
  3. スクロールでヘッダーサイズを変更
  4. ナビゲーションを途中から表示
  5. ナビゲーションが途中から固定され、フッター前で非表示に

1. ナビゲーションが途中から固定

デフォルトでは固定表示されていないナビゲーションを、スクロールして特定のポイントまでいったらCSSのposition: fixed;を使って固定表示させるというもので、今回はナビゲーション部分(ウィンドウ上部からナビゲーション上部)までスクロールされたタイミングで固定にするというものです。
実装にはCSSとjQueryそれぞれに下記を記述します。

CSS

.is-fixed {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
}

jQuery

$(function() {
  var $win = $(window),
      $main = $('main'),
      $nav = $('nav'),
      navHeight = $nav.outerHeight(),
      navPos = $nav.offset().top,
      fixedClass = 'is-fixed';

  $win.on('load scroll', function() {
    var value = $(this).scrollTop();
    if ( value > navPos ) {
      $nav.addClass(fixedClass);
      $main.css('margin-top', navHeight);
    } else {
      $nav.removeClass(fixedClass);
      $main.css('margin-top', '0');
    }
  });
});

まず、CSSで固定表示用のclassを作成します。
今回は.is-fixedというlass名にし、そこにposition: fixed;をはじめとする固定表示時のスタイルを記述しておきます。

次にjQueryですが、動きの内容としてはoffset().topを使って取得したnav要素の表示位置とscrollTop()を使って取得したスクロール量を比較し、スクロール量がnav要素の表示位置以上になったタイミングで先ほど用意した.is-fixedというclassをnav要素に.addClass()で付与するというものになり、先述したように.is-fixedには固定表示時のスタイルが指定されているので、そのclassが付与されたnav要素が固定表示されるというものになります。
また、その下の$main.css('margin-top', navHeight);というのは、単純にnav要素を固定表示にするだけだと、固定表示切り替え後にコンテンツ表示位置がずれるのを防ぐためになります。
ここではmain要素に対してmarginですが、それだと困る場合はbodypaddingとかでもいけます。

あとは、スクロール量がnav要素の表示位置以上でなかった場合として、デフォルトと同じようにnav要素にあるclassとmain要素に追加したmargin-topをそれぞれリセットするような形で記述しておけば、スクロールしたらナビゲーションが途中から固定するという動きを実装することができます。

実際の動きについては以下で確認できます。

目次へ

2. 下にスクロールでヘッダー非表示・上にスクロールでヘッダー表示

こちらは少し前から見かけることが多くなった、スクロールした方向によってヘッダーの表示・非表示を切り替えるというもので、今回は下方向にスクロールした場合はヘッダーが非表示になり、逆に上方向にスクロールした場合はヘッダーが表示されるというものを実装してみます。
実装にはCSSとjQueryそれぞれに下記を記述します。

CSS

header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  transition: .3s;
}

jQuery

$(function() {
  var $win = $(window),
      $header = $('header'),
      headerHeight = $header.outerHeight(),
      startPos = 0;

  $win.on('load scroll', function() {
    var value = $(this).scrollTop();
    if ( value > startPos && value > headerHeight ) {
      $header.css('top', '-' + headerHeight + 'px');
    } else {
      $header.css('top', '0');
    }
    startPos = value;
  });
});

まず、CSSではheader要素に対してposition: fixed;をはじめとする固定表示用のスタイルを指定しますが、その際に表示・非表示の動きにアニメーションを入れるためにtransitionもあわせて指定しておきます。

次にjQueryですが、ざっくりとした説明をするとこちらも先ほどと同様でスクロール量などと条件分岐を組み合わせて、それによってCSSを変化させるといったものになります。
条件としてはスクロールした量が基準位置として用意したstartPosの値より大きい場合は下方向へのスクロール、そうでない場合は上方向へのスクロールという形になっており、下方向へのスクロールの場合はさらにheader要素の高さ以上スクロールされているかというのも条件に加えています。

それぞれの条件によって実行される処理としては、表示・非表示の切り替えとしてCSSのtopの値を変更しています。
単純にtopの値の変更だけだとパッと表示・非表示が切り替わるだけですが、先ほどCSSで記述しておいたtransitionによってアニメーション付きでヘッダーが上に引っ込んだり上から降りてきたりする動きとして実装することができます。

実際の動きについては以下で確認できます。

目次へ

3. スクロールでヘッダーサイズを変更

こちらも見かける機会が多くなったエフェクトのひとつで、スクロールするとヘッダーのサイズが変更されるというものになり、少し手を加えればヘッダー内の要素にも何か変化を付けることができます。
実装にはCSSとjQueryそれぞれに下記を記述します。

CSS

header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  height: 200px;
  background: #3498db;
  transition: .3s;
}
header h1 {
  color: #fff;
  transition: .3s;
}
.is-animation {
  height: 100px;
}
.is-animation h1 {
  color: #000;
}

jQuery

$(function() {
  var $win = $(window),
      $header = $('header'),
      animationClass = 'is-animation';

  $win.on('load scroll', function() {
    var value = $(this).scrollTop();
    if ( value > 100 ) {
      $header.addClass(animationClass);
    } else {
      $header.removeClass(animationClass);
    }
  });
});

まず、CSSではheader要素に対してposition: fixed;をはじめとする固定表示用のスタイルを指定し、今回は高さを変更する動きを加えてみたいので適当なheightも一緒に指定おきます。(ヘッダーを可変にする必要がある場合などは、heightは指定せずにヘッダー内の要素を使ってマージン調整するなどしてください。)
また、サイズ変更時にアニメーションを入れるためにtransitionもあわせて指定しておきます。

次にjQueryですが、こちらはよく見かける少しスクロールするとページ先頭へ戻るボタンが表示される動きと同じような記述で、スクロール量が指定した数値以上(今回のサンプルでは100)になったらヘッダーにclassを付与するというものになります。
あとは、その付与されたclassを用いて変化後のスタイルとしてそれぞれCSSで指定しておけば、スクロールした際にヘッダーに何かしらの動きをつけることが可能です。

今回の場合は高さが変更する動きなので、.is-animationheightの値を最初にheaderに対して指定したものより低く指定しておくと、transitionと組み合わさってアニメーションしながらヘッダーの高さが変化するようになります。
また、サンプルでヘッダーがサイズ変更されるのと同時に中にあるテキストもカラー変更されているように、少し手を加えればヘッダー内の要素に対して何か変化をつけるということもできます。

実際の動きについては以下で確認できます。

目次へ

4. ナビゲーションを途中から表示

ある程度スクロールするまではナビゲーションはそのままの位置で表示され続け、その後一定量スクロールされたらナビゲーションが表示されてくるタイプのものです。
表示される際は上から降りてくるような感じになっており、実装にはCSSとjQueryそれぞれに下記を記述します。

CSS

.clone-nav {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  transition: .3s;
  transform: translateY(-100%);
}
.is-show {
  transform: translateY(0);
}

jQuery

$(function() {
  var $win = $(window),
      $cloneNav = $('nav').clone().addClass('clone-nav').appendTo('body'),
      showClass = 'is-show';

  $win.on('load scroll', function() {
    var value = $(this).scrollTop();
    if ( value > 700 ) {
      $cloneNav.addClass(showClass);
    } else {
      $cloneNav.removeClass(showClass);
    }
  });
});

まず、CSSではある程度スクロールされたら表示させるナビゲーションに関するスタイルを指定していきます。
今回はこのナビゲーションに.clone-navというclassを指定しているので、それに対して固定表示用のスタイル指定とアニメーションに必要になってくるtransitiontransformを指定しておきます。
また、.is-showというclassは、スクロールされたら表示させるナビゲーションが表示するタイミングになったときに上から降りてくるような動きにするために必要になります。

次にjQueryですが、実はこのスクロールされたら表示させるナビゲーションはもともとHTMLで記述されていたナビゲーションをそのまま使用しているのではなく、jQueryの.clone()を使って新たに生成したものになり、スクロールした際に表示・非表示の動きをしているのもこの生成されたナビゲーションになります。
これを「3. スクロールでヘッダーサイズを変更」と同じように、スクロール量が指定した数値以上になったときにclassを付与することで、ナビゲーションが上から降りてくるようなアニメーションをつけることができ、逆に数値以下になった場合は上に隠れていくようになります。

実際の動きについては以下で確認できます。

目次へ

5. ナビゲーションが途中から固定され、フッター前で非表示に

最後は「1. ナビゲーションが途中から固定」で紹介した動きに加え、さらにその固定されたナビゲーションがフッター前までスクロールされたら非表示になるという動きになります。
実装にはCSSとjQueryそれぞれに下記を記述します。

CSS

nav {
  transition: .3s;
}
.is-fixed {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
}
.is-hide {
  transform: translateY(-100%);
}

jQuery

$(function() {
  var $win = $(window),
      $main = $('main'),
      $nav = $('nav'),
      navHeight = $nav.outerHeight(),
      footerHeight = $('footer').outerHeight(),
      docmentHeight = $(document).height(),
      navPos = $nav.offset().top,
      fixedClass = 'is-fixed',
      hideClass = 'is-hide';

  $win.on('load scroll', function() {
    var value = $(this).scrollTop(),
        scrollPos = $win.height() + value;

    if ( value > navPos ) {
      if ( docmentHeight - scrollPos <= footerHeight ) {
        $nav.addClass(hideClass);
      } else {
        $nav.removeClass(hideClass);
      }
      $nav.addClass(fixedClass);
      $main.css('margin-top', navHeight);
    } else {
      $nav.removeClass(fixedClass);
      $main.css('margin-top', '0');
    }
  });
});

まず「1. ナビゲーションが途中から固定」と同様で、CSSで.is-fixedというclass名でposition: fixed;をはじめとする固定表示時のスタイルを記述しておきます。
その他のスタイルとしてはnav要素にtransitionを、.is-hideというclassにtransformを指定しておき、これらはいずれもナビゲーションの表示・非表示とアニメーションで利用するものになります。

次にjQueryですが、ナビゲーションが途中から固定される動きについては「1. ナビゲーションが途中から固定」と同様で、そこにフッター手前で非表示になるような処理を追加していきます。
フッター手前で非表示になる動きは、まずページとフッターの高さをそれぞれ取得し、それらの数値と現在のスクロール量とを組み合わせた条件分岐を利用して実装しています。
条件によって先ほどCSSで記述しておいた.is-hideというclassがナビゲーションに付与されて非表示になり、逆に条件を満たない場合はそのclassが削除されて再度表示されます。

実際の動きについては以下で確認できます。

目次へ


以上、jQueryを使ってスクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコードでした。
以前と違ってアニメーションなどもCSSで簡単に実装できるようになったので、.addClass().removeClass()するだけでもいろいろできるようになりましたね。
他の動きと組み合わせたりとか処理回数を減らしたいとかになるといろいろ手直しが必要な部分もありますが、とりあえず上で紹介してきたような感じでスクロールによって固定させたり変化させたりという動きの実装はできると思います。

Close the search window,
please press close button or esc key.