ホームページの作成や運用ノウハウについて、プロのクリエイターが情報を無料公開!

ホームページTIPS
facebook twitter mail

このサイトはコーディング初心者〜中級者向けの情報サイトです。掲載コードの転用制限はありませんが、
動作保証は行なっておりません。ご意見については、フォームからお知らせください。

javascriptに関するTips

更新日:2019.10.4

サイドナビをコンテンツのスクロール量に合わせて追従(固定〜解除)させる方法

解 説

サイドナビがあるページをスクロールさせる際、コンテンツの長さに応じてサイドナビを追従表示(ある位置で固定〜最後に解除)させる方法についてご紹介します。まず最初にjQueryは読み込んでおきましょう。

1htmlの構造は以下のように作ります。
 ※ここにはメインのコンテンツを記載  ※ここにはメインのコンテンツを記載  ※ここにはメインのコンテンツを記載  ※ここにはメインのコンテンツを記載
 ※サイドナビの中身をclass="○○○_inner"などで括ります  
  ※ここにサイドナビを記載   ※ここにサイドナビを記載   ※ここにサイドナビを記載   ※ここにサイドナビを記載  

上記のようにメインコンテンツとサイドナビの階層を並列にします。

サイドナビについては、中身をclass=”○○○_inner”などで括ります。

2サイドナビが最後までスクロールしたらそこで固定する
/*  <サイドナビの仕様>
    ページによってサイドナビの長さが異なってもOK。
    メインのコンテンツより、サイドナビが短い場合に、サイドナビが最後まで行ったらそこで固定される。
    加えて、ウィンドウよりもサイドナビが短い場合は、上に固定される。
*/

$(window).load(function () {
	
    var w = $(window).width();
    var x = 768;				//768px以上(PC/タブレット)で発動
    if (w >= x) {
	
		
		//該当のセレクタなどを代入

		var mainArea = $(".main_content");       /*メインコンテンツ*/
		var sideWrap = $(".side_Nav");           /*サイドナビの外枠*/
		var sideArea = $(".side_Nav_inner");     /*サイドナビの中身*/

		var wd = $(window); 

		var mainH = mainArea.height();
		var sideH = sideWrap.height();


		if(sideH < mainH) { //メインの方が高ければ処理する

			//サイドナビの外枠をメインと同じ高さにしてrelaltive指定(#sideをポジションで上や下に固定するため)
			sideWrap.css({"height": mainH,"position": "relative"});

			//サイドナビがウィンドウよりいくらはみ出してるか
			var sideOver = wd.height()-sideArea.height();

			 //固定を開始する位置 = サイドナビの座標+はみ出す距離
			var starPoint = sideArea.offset().top + (-sideOver);

			//固定を解除する位置 = メインコンテンツの終点
			var breakPoint = sideArea.offset().top + mainH;

			wd.scroll(function() {  //スクロール中の処理


				if(wd.height() < sideArea.height()){ //サイドナビが画面より大きい場合
					if(starPoint < wd.scrollTop() && wd.scrollTop() + wd.height() < breakPoint){ //固定範囲内
						sideArea.css({"position": "fixed","bottom": "20px"}); 

					}else if(wd.scrollTop() + wd.height() >= breakPoint){ //固定解除位置を超えた時
						sideArea.css({"position": "absolute", "bottom": "0"});

					} else { //その他、上に戻った時
						sideArea.css("position", "static");

					}

				}else{ //サイドナビが画面より小さい場合

					var sideBtm = wd.scrollTop() + sideArea.height();  //サイドナビの終点

					if(mainArea.offset().top < wd.scrollTop() && sideBtm < breakPoint){ //固定範囲内
						sideArea.css({"position": "fixed", "top": "20px"});

					}else if(sideBtm >= breakPoint){ //固定解除位置を超えた時

						//サイドナビ固定場所(bottom指定すると不具合が出るのでtopからの固定位置を算出する)
						var fixedSide = mainH - sideH;

						sideArea.css({"position": "absolute", "top": fixedSide});

					} else {
						sideArea.css("position", "static");
					}
				}


			});

		} 
		
	}//PC/タブレットで発動のif
});

まず最初にjQueryは読み込んでおいてから、上記のjavascriptを書きます。

コードが長いので「side-nav.js」など別ファイルにして、headに読み込ませると良いでしょう。

このスクリプトでは、スマートフォン以外(画面の横幅  768px以上)で発動し、

メインのコンテンツよりサイドナビが短い場合に、

サイドナビが最後までスクロールしたらそこで固定される動きになります。

 

もう1つ、別の動きかたについてもご紹介します。

 

 

3サイドナビを画面上部で固定し、コンテンツが最後までスクロールする直前に解除する
jQuery(function($){
    var w = jQuery(window).width();
    var x = 768;    //768px以上(PC/タブレット)で発動
    if (w >= x) {
        
        var content = jQuery(".main_content");
        var sidebar = jQuery(".side_Nav");
        var sticked = jQuery(".side_Nav_inner");

        // サイドナビの位置
        var sidebar_top = sidebar.offset().top;
        // 固定するナビの元々の位置
        var sticked_original_top = sticked.offset().top;
        // 固定するナビの高さ
        var sticked_height = sticked.height();
        // メインコンテンツの高さ
        var content_height = content.height();

        //メインコンテンツの高さがナビより大きい時に発動
        if(content_height > sticked_height){
            // スクロールかリサイズ時
            jQuery(window).on('scroll resize', function(){
                // 現在の位置
                var scrollTop = jQuery(document).scrollTop();
                // メインコンテンツ最後尾
                var content_bottom = content.offset().top + content.height();

                if ((scrollTop > sticked_original_top) && (scrollTop < content_bottom - sticked_height)){
                    // 現在位置が、初期位置より下で、メインコンテンツ最後尾より上なら、画面上部にサイドナビを固定
                    sticked.css({'position': 'fixed',
                        'top': 0, 
                        'width': sidebar.width()
                    });
                } else if(scrollTop >= content_bottom - sticked_height){
                    // 現在位置がメインコンテンツ最後尾より下なら、メインコンテンツ最後尾にサイドナビを位置させる
                    sticked.css({'position': 'absolute',
                        'top': content_bottom - sticked_height - sidebar_top,
                        'width': sidebar.width()
                    });
                } 
                 else {
                // 現在位置が初期位置より上なら、何もしない
                sticked.css({'position': 'static'});
                }
            });
        }
    }
});

このスクリプトでは、発動条件は同じで、

サイドナビを画面上部で固定、コンテンツが最後までスクロールする直前に解除させる動きです。

どちらが良いという事はありませんので、コンテンツ、サイドナビのスクロールボリュームや、

お好みに合わせて使い分けてください。

トップへ