【jQuery】1ページ内の現在地を表示するナビゲーションの作り方

ページ内の現在地を教えてくれる、ワンページナビゲーション。

プラグイン無しで使いまわせるシンプルなものを作ってみた。

完成コード

こういうやつです。

解説

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>ワンページナビ</title>

  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script src="script.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <nav>
    <ul>
      <li><a class="js-curnav-switch" href="#menu1">menu1</a></li>
      <li><a class="js-curnav-switch" href="#menu2">menu2</a></li>
      <li><a class="js-curnav-switch" href="#menu3">menu3</a></li>
      <li><a class="js-curnav-switch" href="#menu4">menu4</a></li>
    </ul>
  </nav>
  <main>
    <section id="menu1">
      content1
    </section>
    <section id="menu2">
      content2
    </section>
    <section id="menu3">
      content3
    </section>
    <section id="menu4">
      content4
    </section>
  </main>
    
</body>
</html>

ナビゲーションのaタグにそれぞれ「js-curnav-switch」のクラス名を付与し、idにリンク設定する。

idを付与されたHTMLタグの位置でメニューが切り替わるように設定します。

style.css(scss)

nav {
  width: 100%;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 60px;
  background: rgba(0,0,0,.2);
  ul {
    display: flex;
    justify-content: center;
    a {
      display: block;
      margin: 0 10px;
      line-height: 60px;
      text-decoration: none;
      color: #000;
      font-weight: bold;
      &.is-current {
        color: #f00;
      }
    }
  }
}
main {
  padding-top: 60px;
}
section {
  min-height: 400px;
  padding: 20px;
  text-align: center;
  &:nth-child(1) { background: #fee; }
  &:nth-child(2) { background: #efe; }
  &:nth-child(3) { background: #eef; }
  &:nth-child(4) { background: #fef; }
}

見た目上わかりやすくするために整えただけです。

script.js

 function onePageNav( switchName ) {
// 変数設定
    const navSwitch = $(switchName);
    const deductHeight = 60;//ここに設定した数字を引いた位置にスクロールした時点で切り替わる
    let navArr = [];

// ナビゲーションに設定したクラスのリンク先idを取得して、それぞれのid名とtop offsetの値を配列に追加します
    navSwitch.each(function(i){
      let navSwitchHref = $(this).attr('href');
      let tgtOff = $(navSwitchHref).offset().top - deductHeight;
      navArr.push([]);
      navArr[i].switch = $(this);
      navArr[i].tgtOff = tgtOff;
    });

// スクロールするたびに、どのナビゲーションのリンク先にいるか判別して、.is-currentクラスを切り替える
    $(window).scroll(function () {
      for( let i = 0; i < navArr.length; i++ ){
        let scroll = $(window).scrollTop();
        let tgtKey = navArr[i];
        let tgtSwitch = tgtKey.switch;
        let tgtOff = tgtKey.tgtOff;
        if ( scroll > tgtOff ) {
          navSwitch.removeClass('is-current');
          tgtSwitch.addClass('is-current');
        } else {
          tgtSwitch.removeClass('is-current');
        }
      }
    });
  }
  $(window).on('load resize',function(){
 // リサイズのたびにターゲットのtop offsetが変わるので、loadとresizeごとに実行する
    onePageNav('.js-curnav-switch');//ここでナビゲーションリンクのクラスを指定する。
  });

ナビゲーションのクラス以外は、リンク先等変更してもJSを編集する必要のない書き方になっています。

もっとスマートな書き方がありましたらお教えくださいませ。

では、よいjQueryライフを。