jQuery スクロールに追従するサイドバー
最近はあまり見なくなりましたが、スクロールに追従(スクロールしても固定)するサイドバーをjQueryで書く案件があったのでブログの記事にしておきます。
この記事で使うイベントやメソッドなど
.scrollTop();
.css('prop', 'value');
$(window).scroll(function() { Do Something });
ヘッダーとフッターがあり、メインのコンテンツとサイドバーがある簡単な2カラムレイアウトで考えます。(都合上サイドバーは.side-barの中に追従するコンテンツを入れるといった入れ子のマークアップをします。)
このレイアウトで追従して欲しいサイドバーの追従範囲はコンテンツの高さです。スクロールしてヘッダーが見えなくなった場所でサイドバーをページ上部に固定します。追従を解除する場所はフッターがサイドバーの最下部に到達した場所です。
まずは各要素の高さをそれぞれ変数に入れましょう。追従する範囲となるサイドバーの高さをコンテンツの高さと揃えます。合わせて追従を解除する場所(ヘッダーの高さとコンテンツの高さを足した値から追従するサイドバーの高さを引いた値)も変数に入れます。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
});
スクロールイベントが始まると、どれだけスクロールしたかを監視します。どれだけスクロールしたかのスクロール量はjQueryのメソッドである.scrollTop()
で求めることができます。
追従を開始する場所と解除する場所に来たらそれぞれjQueryでCSSのプロパティを変更します。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
//イベント開始
$(window).scroll(function() {
//スクロール量
var scrollVal = $(window).scrollTop();
});
});
ここからはif〜else if〜else文で条件を指定していきます。
if 追従区間 { 追従 } else if 追従解除位置 { 追従解除 } else { 通常 } と言う条件になります。
追従区間はスクロール量 > ヘッダーの高さ かつ 追従解除する場所 > スクロール量になります。
この条件になったら.css()
でposition: fixed; top: 0;
にします。
追従解除位置はスクロール量 > 追従解除する場所になります。
この条件になったらposition: absolute; bottom: 0
にします。
通常(追従範囲外)の場合はposition: static;
とします。
jQuery Code
$(function() {
//各要素の高さ
var headerHeight = $('.page-header').height();
var contentsHeight = $('.page-body').height();
var fixedSideBarHeight = $('#fixed-side-bar').height();
//サイドバーの高さをコンテンツの高さと揃える
$('.side-bar').css('height', contentsHeight);
//追従を解除する場所
var scrollStopPos = headerHeight+contentsHeight-fixedSideBarHeight;
//イベント開始
$(window).scroll(function() {
//スクロール量
var scrollVal = $(window).scrollTop();
//追従区間
if(headerHeight < scrollVal && scrollStopPos > scrollVal) {
$('#fixed-side-bar').css({
'position': 'fixed',
'top': '0'
});
//追従解除
} else if(scrollStopPos < scrollVal) {
$('#fixed-side-bar').css({
'position': 'absolute',
'top': '',
'bottom': '0'
});
//デフォルト
} else {
$('#fixed-side-bar').css('position', 'static');
}
});
});