MENU

【jQuery】スクロール追従カレント表示

スクロールに追従したナビゲーション(ページ内リンク)のカレント表示についてのコード記録。

目次

カレント表示とは

こんな感じのアニメーション。(動画右上のナビゲーションリンクのアンダーバー)

ページ内をスクロールすると各セクションと紐づいたナビゲーションリンクにアニメーションが付与される。

ページ内のどこを見ているのかわかりやすく、ユーザフレンドリーなサイトに。

JavaScriptコード(jQuery)

$(function () {
  // navカレント表示
  var set = 200; //ウインドウ上部からどれぐらいの位置で変化させるか
  var boxTop = new Array();
  var current = -1;
  //各要素の位置
  //position-nowは場所を取得したい対象の要素に付ける
  $(".position-now").each(function (i) {
    boxTop[i] = $(this).offset().top;
  });
  //最初の要素にclass="position-now"をつける
  changeBox(0);
  //スクロールした時の処理
  $(window).scroll(function () {
    scrollPosition = $(window).scrollTop();
    for (var i = boxTop.length - 1; i >= 0; i--) {
      if ($(window).scrollTop() > boxTop[i] - set) {
        changeBox(i);
        break;
      }
    }
  });
  //ナビの処理
  function changeBox(secNum) {
    if (secNum != current) {
      current = secNum;
      secNum2 = secNum + 1; //以下にクラス付与したい要素名と付与したいクラス名
      $(".header nav ul li a").removeClass("link-current");

      //位置によって個別に処理をしたい場合
      if (current == 0) {
        $("#about_link_js").addClass("link-current");
        // 現在地がsection1の場合の処理
      } else if (current == 1) {
        $("#skills_link_js").addClass("link-current");
        // 現在地がsection2の場合の処理
      } else if (current == 2) {
        // 現在地がsection3の場合の処理
        $("#service_link_js").addClass("link-current");
      } else if (current == 3) {
        // 現在地がsection4の場合の処理
        $("#flow_link_js").addClass("link-current");
      } else if (current == 4) {
        // 現在地がsection5の場合の処理
        $("#works_link_js").addClass("link-current");
      } else if (current == 5) {
        // 現在地がsection6の場合の処理
        $("#contact_link_js").addClass("link-current");
      }
    }
  }
});

$(function () {
  // スムーススクロール
  $('a[href^="#"]').click(function () {
    let header = $(".header").innerHeight();
    let speed = 500;
    let id = $(this).attr("href");
    let target = $("#" == id ? "html" : id);
    let position = $(target).offset().top - header;
    $("html, body").animate(
      {
        scrollTop: position,
      },
      speed
    );
    return false;
  });
});

実装手順

jQueryコードをコピペ

上記jQueryコードをコピペ。

※ラストのスムーススクロールのコードは、既に記述済みの場合は除外。

カレント判定したいタグ全てにクラス付与

カレント判定したいタグ(ナビゲーションに記載しているsectionやdiv)全てにclass=“position-now” を付与。

各navメニューに固有のidを付与

各navメニューに任意のidを付与(例えばid=”**_link_js”のように付けておく)。

30行目付近の 「//位置によって個別に処理をしたい場合」内のid名(#top_link_js等)を任意の内容に書き換える。

※このコピペ用コードはナビメニューが5つの場合(current0~4)を想定。増やしたい場合は追加する数だけ else if{} を増やしす、減らす場合は else if{} を減らす。

ページ内リンクを付ける

例えばナビゲーション内のaboutならhref="#about"とし、それに紐づくtopセクションにid=”top”を付与。

CSSにアニメーション用スタイルを付与

好きなスタイルを付与する。

例:黒の下線

.link-current {
  border-bottom: 2px solid #fff;
}

カレント表示させたい要素を指定

27行目付近の.header-nav li aの部分にカレント表示させたい任意の要素を指定。

→各々のナビゲーション、リンクを指定する。

アニメーションのタイミング調整

タイミング調整は3行目付近の

var set = 250;

の数値をいじる。

(補足)スムーススクロール設定

固定ヘッダーを想定し、ヘッダー分の高さを差し引く処理を入れてある為、必要に応じて修正。

対象は下記部分。

let header = $(".header").innerHeight();
let position = $(target).offset().top - header;

実装例に対応したHTML,CSSコード例

実装例のスクリプトを記載したHTML,CSSコードの参考コード。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <!-- jquery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

    <style>
      @charset "UTF-8";
      /*==========================================================================
      # reset
      ==========================================================================*/
      *,
      ::before,
      ::after {
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
      }

      html,
      body,
      h1,
      h2,
      h3,
      h4,
      h5,
      h6,
      ul,
      ol,
      dl,
      li,
      dt,
      dd,
      p,
      div,
      span,
      img,
      a,
      table,
      tr,
      th,
      td {
        margin: 0;
        padding: 0;
        border: 0;
        font-weight: normal;
        font-size: 100%;
        vertical-align: baseline;
      }

      header,
      footer,
      nav,
      section,
      article,
      main,
      aside,
      figure,
      figcaption {
        display: block;
      }

      ol,
      ul {
        list-style: none;
        list-style-type: none;
      }

      img {
        max-width: 100%;
        height: auto;
        vertical-align: middle;
      }

      a {
        color: inherit;
        text-decoration: none;
      }

      /*==========================================================================
      # カレント表示
      ==========================================================================*/
      .link-current {
        border-bottom: 2px solid #000;
      }

      /*==========================================================================
      # body内
      ==========================================================================*/
      .header {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 80px;
        background: #bbbbbb;
      }
      .header nav {
        position: relative;
        height: inherit;
      }
      .header nav ul {
        height: inherit;
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-pack: center;
        -ms-flex-pack: center;
        justify-content: center;
        -webkit-box-align: center;
        -ms-flex-align: center;
        align-items: center;
      }
      .header nav ul li {
        list-style: none;
      }
      .header nav ul li:not(:first-child) {
        margin-left: 40px;
      }
      main {
        margin-top: 80px;
      }

      .section {
        height: 600px;
      }
      .section:nth-child(2n + 1) {
        background: #d2ffbb;
      }
      .section:nth-child(2n) {
        background: #bbc6ff;
      }
      .section:last-child {
        margin-bottom: 300px;
      }

      .section-head {
        text-align: center;
        font-size: 40px;
      }
    </style>

    <script>
      $(function () {
        // navカレント表示
        var set = 200; //ウインドウ上部からどれぐらいの位置で変化させるか
        var boxTop = new Array();
        var current = -1;
        //各要素の位置
        //position-nowは場所を取得したい対象の要素に付ける
        $(".position-now").each(function (i) {
          boxTop[i] = $(this).offset().top;
        });
        //最初の要素にclass="position-now"をつける
        changeBox(0);
        //スクロールした時の処理
        $(window).scroll(function () {
          scrollPosition = $(window).scrollTop();
          for (var i = boxTop.length - 1; i >= 0; i--) {
            if ($(window).scrollTop() > boxTop[i] - set) {
              changeBox(i);
              break;
            }
          }
        });
        //ナビの処理
        function changeBox(secNum) {
          if (secNum != current) {
            current = secNum;
            secNum2 = secNum + 1; //以下にクラス付与したい要素名と付与したいクラス名
            $(".header nav ul li a").removeClass("link-current");

            //位置によって個別に処理をしたい場合
            if (current == 0) {
              $("#about_link_js").addClass("link-current");
              // 現在地がsection1の場合の処理
            } else if (current == 1) {
              $("#skills_link_js").addClass("link-current");
              // 現在地がsection2の場合の処理
            } else if (current == 2) {
              // 現在地がsection3の場合の処理
              $("#service_link_js").addClass("link-current");
            } else if (current == 3) {
              // 現在地がsection4の場合の処理
              $("#flow_link_js").addClass("link-current");
            } else if (current == 4) {
              // 現在地がsection5の場合の処理
              $("#works_link_js").addClass("link-current");
            } else if (current == 5) {
              // 現在地がsection6の場合の処理
              $("#contact_link_js").addClass("link-current");
            }
          }
        }
      });

      $(function () {
        // スムーススクロール
        $('a[href^="#"]').click(function () {
          let header = $(".header").innerHeight();
          let speed = 500;
          let id = $(this).attr("href");
          let target = $("#" == id ? "html" : id);
          let position = $(target).offset().top - header;
          $("html, body").animate(
            {
              scrollTop: position,
            },
            speed
          );
          return false;
        });
      });
    </script>
  </head>

  <body>
    <header class="header">
      <nav>
        <ul>
          <li><a id="about_link_js" href="#about">About</a></li>
          <li><a id="skills_link_js" href="#skills">Skills</a></li>
          <li><a id="service_link_js" href="#service">Service</a></li>
          <li><a id="flow_link_js" href="#flow">Workflow</a></li>
          <li><a id="works_link_js" href="#works">Works</a></li>
          <li><a id="contact_link_js" href="#contact">Contact</a></li>
        </ul>
      </nav>
    </header>
    <!-- /.header -->

    <main>
      <section class="section position-now" id="about about_link_js">
        <h2 class="section-head">About</h2>
      </section>
      <!-- /.about -->

      <section class="section position-now" id="skills skills_link_js">
        <h2 class="section-head">Skills</h2>
      </section>

      <section class="section position-now" id="service service_link_js">
        <h2 class="section-head">Service</h2>
      </section>
      <!-- /.service -->

      <section class="section position-now" id="flow flow_link_js">
        <h2 class="section-head">Work Flow</h2>
      </section>
      <!-- /.flow -->

      <section class="section position-now" id="works works_link_js">
        <h2 class="section-head">Works</h2>
      </section>
      <!-- /.works -->

      <section class="section position-now" id="contact contact_link_js">
        <h2 class="section-head">Contact</h2>
      </section>
      <!-- /.contact -->
    </main>
  </body>
</html>
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

CAPTCHA


目次