Web制作 プログラミング

[jQueryで実現]サイドバーを追従させ、位置によってナビゲーションの表示も変える方法

この記事は約 6 分で読めます。

この記事は下記のような悩みを持った方にオススメです
・サイドバーを追従させたい
・位置によってナビゲーションの表示方法を変えたい

はじめに

「jQueryでサイドバーを追従させる方法」は山ほど出てきたのですが、

「サイドバーを追従させつつ、位置によってナビゲーションメニューの色を変えたりしたいな」

と思ったときにその方法が書いてある情報が少なかったので解説します。

デモ

デモはこちらになります。

このように、スクロールすると、そのコンテンツの名前の部分にボーダーがつくようになります。

また、一番下まで行くと追従を辞めるような工夫も入れました。

また、javascriptのコードは下記記事を参考にしました。ありがとうございます。

解説

それでは解説していきます

スクロールによる追従

まずはスクロールによる追従です。
コードは下記のようになっています。

$(function() {
  var $fixElement = $('.sidebar_list'); // 追従する要素(サイドバーの中身)
  var $sidebar = $('.sidebar'); 
  var $sidebarHeight = $sidebar.offset().top + $sidebar.height();//サイドバーの一番下までの高さ
  var baseFixPoint = $fixElement.offset().top; // 追従する要素の初期位置
  var fixClass = 'is_fixed'; // 追従するためのクラス
  var absoClass = 'is_absolute'; // 一番下まで行ったときにつけるクラス

  // 要素が追従する処理
  function fixFunction() {
      var windowScrolltop = $(window).scrollTop();
      // サイドバーを超したときは追従を辞める
      if(windowScrolltop >= $sidebarHeight - $fixElement.height()){ 
        $fixElement.addClass(absoClass);
        $fixElement.removeClass(fixClass);
      } else if(windowScrolltop >= baseFixPoint) {
        // サイドバーの中の時は追従
          $fixElement.addClass(fixClass);
          $fixElement.removeClass(absoClass);
      } else {
        // 一番上では場所を固定しない
          $fixElement.removeClass(fixClass);
          $fixElement.removeClass(absoClass);
      }
  }

  $(window).on('load scroll', function() {
      fixFunction();
  });
});

基本的にはコメントの通りなのですが、

  • 一番上(サイドバーの高さに達してないとき)・・・なにもクラスを与えない
  • コンテンツがある区間の時・・・position:fix;を与え、画面一番上に固定
  • サイドバーを過ぎたとき・・・position:absolute;を与え、サイドバーの一番下に固定。よって、スクロールに沿って消えていく

というように処理を加えています。

スクロールに応じてナビゲーションのデザインを変える

$(function() {
  // ナビゲーションのリンクを指定
 var navLink = $('ul.sidebar_list li a');

  // 各コンテンツのページ上部からの開始位置と終了位置を配列に格納しておく
 var contentsArr = new Array();
for (var i = 0; i < navLink.length; i++) {
     // コンテンツのIDを取得
    var targetContents = navLink.eq(i).attr('href');
    // ページ内リンクでないナビゲーションが含まれている場合は除外する
    if(targetContents.charAt(0) == '#') {
       // ページ上部からコンテンツの開始位置までの距離を取得
          var targetContentsTop = $(targetContents).offset().top;
       // ページ上部からコンテンツの終了位置までの距離を取得
          var targetContentsBottom = targetContentsTop + $(targetContents).outerHeight(true) - 1;
       // 配列に格納
          contentsArr[i] = [targetContentsTop, targetContentsBottom]
    }
 };

コードはこの部分になります。先ほどの参考サイトのほとんど同じコードです。

簡単に説明すると、id属性が与えられているものを1つずつ取り出し、その一番上の高さと一番下の高さを配列に格納しています。
これを下記コードの部分で現在地と高さを見比べて、その部分のidに「actionクラス」(色を付けるクラス)をつけるようになっています。

function currentCheck() {
    // 現在のスクロール位置を取得
    var windowScrolltop = $(window).scrollTop()
    for (var i = 0; i < contentsArr.length; i++) {
      // 現在のスクロール位置が、配列に格納した開始位置と終了位置の間にあるものを調べる
      if (
        contentsArr[i][0] <= windowScrolltop &&
        contentsArr[i][1] >= windowScrolltop
      ) {
        // 開始位置と終了位置の間にある場合、ナビゲーションにclass="current"をつける
        navLink.removeClass('action')
        navLink.eq(i).addClass('action')
        i == contentsArr.length
      }
    }
  }

まとめ

サイドバー追従だけならそこまで難しくないですが、位置によってナビゲーションメニューに処理を加えようとした瞬間に難しくなりますね...

ですが、企業サイトなどの作成に良く出てくるものなのでこの技術を取得すると便利です!

-Web制作, プログラミング

© 2021 AGATA CODE Powered by AFFINGER5