一度は見かけたことがあると思う、スクロールしたらヘッダーやナビゲーションを固定表示させたり見栄えを変化させたりする動きをjQueryで実装するサンプルです。途中から要素を固定させたり、スクロールした方向によって表示・非表示を切り替えたりなど全5種類です。
※プレフィックスは必要に応じて追記してください。
※以下で紹介している方法はいずれもjQueryを使用していますので、あらかじめ読み込ませてください。
※適用させる要素やクラス名などの各変数については、自身の環境にあわせて変更してください。
使用するHTML
特にこのようにしなければいけないというものではないですが、今回のサンプルで使用しているHTMLはいずれも下記のようなもの(サンプルによってはnav
要素がないものもあります)になっており、このHTMLにあるheader
やnav
要素に対してjQueryで処理していくといった感じになります。
HTML
<header>
...
</header>
<nav>
...
</nav>
<main>
...
</main>
<footer>
...
</footer>
jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5 目次
1. ナビゲーションが途中から固定
デフォルトでは固定表示されていないナビゲーションを、スクロールして特定のポイントまでいったらCSSのposition: fixed;
を使って固定表示させるというもので、今回はナビゲーション部分(ウィンドウ上部からナビゲーション上部)までスクロールされたタイミングで固定にするというものです。
実装にはCSSとjQueryそれぞれに下記を記述します。
CSS
.is-fixed {
position: fixed;
top: 0;
left: 0;
z-index: 2;
width: 100%;
}
jQuery
$(document).ready(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で固定表示用のクラスを作成します。
今回は.is-fixed
というクラス名にし、そこにposition: fixed;
をはじめとする固定表示時のスタイルを記述しておきます。
次にjQueryですが、動きの内容としてはoffset().top
を使って取得したnav
要素の表示位置とscrollTop()
を使って取得したスクロール量を比較し、スクロール量がnav
要素の表示位置以上になったタイミングで先ほど用意した.is-fixed
というクラスをnav
要素に.addClass()
で付与するというものになり、先述したように.is-fixed
には固定表示時のスタイルが指定されているので、そのクラスが付与されたnav
要素が固定表示されるというものになります。
また、その下の$main.css('margin-top', navHeight);
というのは、単純にnav
要素を固定表示にするだけだと、固定表示切り替え後にコンテンツ表示位置がずれるのを防ぐためになります。
ここではmain
要素に対してmargin
ですが、それだと困る場合はbody
にpadding
とかでもいけます。
あとは、スクロール量がnav
要素の表示位置以上でなかった場合として、デフォルトと同じようにnav
要素にあるクラスとmain
要素に追加したmargin-top
をそれぞれリセットするような形で記述しておけば、スクロールしたらナビゲーションが途中から固定するという動きを実装することができます。
実際の動きについては以下で確認できます。
2. 下にスクロールでヘッダー非表示・上にスクロールでヘッダー表示
こちらは少し前から見かけることが多くなった、スクロールした方向によってヘッダーの表示・非表示を切り替えるというもので、今回は下方向にスクロールした場合はヘッダーが非表示になり、逆に上方向にスクロールした場合はヘッダーが表示されるというものを実装してみます。
実装にはCSSとjQueryそれぞれに下記を記述します。
CSS
header {
position: fixed;
top: 0;
left: 0;
z-index: 2;
width: 100%;
transition: .3s;
}
jQuery
$(document).ready(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
$(document).ready(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)になったらヘッダーにクラスを付与するというものになります。
あとは、その付与されたクラスを用いて変化後のスタイルとしてそれぞれCSSで指定しておけば、スクロールした際にヘッダーに何かしらの動きをつけることが可能です。
今回の場合は高さが変更する動きなので、.is-animation
でheight
の値を最初に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
$(document).ready(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
というクラスを指定しているので、それに対して固定表示用のスタイル指定とアニメーションに必要になってくるtransition
とtransform
を指定しておきます。
また、.is-show
というクラスは、スクロールされたら表示させるナビゲーションが表示するタイミングになったときに上から降りてくるような動きにするために必要になります。
次にjQueryですが、実はこのスクロールされたら表示させるナビゲーションはもともとHTMLで記述されていたナビゲーションをそのまま使用しているのではなく、jQueryの.clone()
を使って新たに生成したものになり、スクロールした際に表示・非表示の動きをしているのもこの生成されたナビゲーションになります。
これを「3. スクロールでヘッダーサイズを変更」と同じように、スクロール量が指定した数値以上になったときにクラスを付与することで、ナビゲーションが上から降りてくるようなアニメーションをつけることができ、逆に数値以下になった場合は上に隠れていくようになります。
実際の動きについては以下で確認できます。
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
$(document).ready(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
というクラス名でposition: fixed;
をはじめとする固定表示時のスタイルを記述しておきます。
その他のスタイルとしてはnav
要素にtransition
を、.is-hide
というクラスにtransform
を指定しておき、これらはいずれもナビゲーションの表示・非表示とアニメーションで利用するものになります。
次にjQueryですが、ナビゲーションが途中から固定される動きについては「1. ナビゲーションが途中から固定」と同様で、そこにフッター手前で非表示になるような処理を追加していきます。
フッター手前で非表示になる動きは、まずページとフッターの高さをそれぞれ取得し、それらの数値と現在のスクロール量とを組み合わせた条件分岐を利用して実装しています。
条件によって先ほどCSSで記述しておいた.is-hide
というクラスがナビゲーションに付与されて非表示になり、逆に条件を満たない場合はそのクラスが削除されて再度表示されます。
実際の動きについては以下で確認できます。
以上、jQueryを使ってスクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコードでした。
以前と違ってアニメーションなどもCSSで簡単に実装できるようになったので、.addClass()
と.removeClass()
するだけでもいろいろできるようになりましたね。
他の動きと組み合わせたりとか処理回数を減らしたいとかになるといろいろ手直しが必要な部分もありますが、とりあえず上で紹介してきたような感じでスクロールによって固定させたり変化させたりという動きの実装はできると思います。