2017/11/09

サイドバーをスライドして追従表示させる方法

記事やコンテンツボリュームが多い場合、サイドバーよりコンテンツのほうが長くなりますよね。スクロールして途中からサイドバーが切れてしまいますが、サイドバーが下までいくとその場で固定するようにしたときの方法をご紹介します。

前置きとしてこの記事はPCでの表示方法です。スマホの場合サイドバーが固定されてしまうと邪魔になるのでスマホの場合は無効になるように設定しています。

設置方法

まずは、jQueryの読み込みをしておきましょう。
読み込んだら、下記のjavascriptを適当な名前を付けて保存し、サーバーにファイルをアップロードしてください。

例 : side-fixed.jsと名前を付けてjsフォルダにアップするとき

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript" src="js/side-fixed.js"></script>

javascript

$(window).load(function () {
      //該当のセレクタなどを代入
      var mainArea = $("#main"); //メインコンテンツ
      var sideWrap = $("#sideWrap"); //サイドバーの外枠
      var sideArea = $("#side"); //サイドバー
      /*設定ここまで*/
      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");
                        }
                  }
            });
      } 
});

HTML

<div id="header">
<p>ヘッダー。</p>
</div><!-- / #header -->

<div id="contents">

<div id="main">
<p>コンテンツ。</p>
</div><!-- / #main -->

<div id="sideWrap">
<div id="side">
<p>サイドバー。</p> 
</div><!-- / #side -->
</div><!-- / #sideWrap -->

</div><!-- / #contents -->

<div id="footer">
<p>フッター。</p>
</div><!-- / #footer -->

ここでのポイントがコンテンツを#main サイドバーを#sideその周りを#sidewrapで囲ってあげること。

 

スマホの場合の切り替え

レスポンシブサイトの場合スマホのときは固定表示させなくていいのでスマホのときにはjavascriptを読み込まないようにするか、サイドバー自体を非表示にさせる必要があります。

javascriptをユーザーエージェントによって読み込ませないようにする

先ほど書いたjavascriptを下記のコードで囲ってあげま。ユーザーエージェントを判断してスマホで閲覧したときは無効になるようにします。

if(!navigator.userAgent.match(/(iPhone|iPad|iPod|Android)/)){
//ここに実行したい処理を書くとスマホでは無効になります
}

今回参考にさせて頂いたページ

ちょうど固定表示させる方法を探していただので助かりました。

参考 : サイドメニューが下まで行ったらそこで固定するJS(jQuery)