WORKS

スクロール連動ナビゲーション

スクロール連動ナビゲーション

コーディングスキル

HTML5/CSS3

プログラミングスキル

Javascript

WEBページによく見られる、スクロールに連動してナビゲーションの項目にアクションが起きるものです。職業訓練校の朝礼用に作成しました。
サンプルページ01(PC専用)>>

サンプル

今回ご紹介するのは、画面スクロールに連動して、ナビゲーションメニューのデザインを変える方法です。連動させるナビゲーションをposition:fixedやposition:stickyなどで画面に固定して使います。セクションの切り替わりに合わせてメニューが目立ってくれるので、UIとしても分かりやすいです。

スクロール連動ナビゲーション

私が調べたところ、実装する方法は2種類ありました。jQueryのスクロールイベントを用いる方法と、intersection observer(交差監視)というAPI(あるソフトウェアの機能を別のソフトウェアから呼び出す仕組み)を用いる方法です。今回はより簡易に実装できるjQueryのスクロールイベントを用いる方法をご紹介してから、最後におまけでintersection observer APIについて少しだけ触れようと思います。

HTML

HTMLはいたってシンプルです。ナビゲーションとなるリストにaタグを記述し、各コンテンツのブロック要素にidを指定してページ内リンクを付与します。このとき紐づけされたリストとコンテンツが、そのままスクロールに連動するようになります。

<main>
    <aside>
        <ul id="indexList">
            <li><a href="#sec01">sec01</a></li>
            <li><a href="#sec02">sec02</a></li>
            <li><a href="#sec03">sec03</a></li>
            <li><a href="#sec04">sec04</a></li>
            <li><a href="#sec05">sec05</a></li>
        </ul>
    </aside>
    <div class="contents">
        <section id="sec01" class="box">sec01</section>
        <section id="sec02" class="box">sec02</section>
        <section id="sec03" class="box">sec03</section>
        <section id="sec04" class="box">sec04</section>
        <section id="sec05" class="box">sec05</section>
    </div>
</main>

CSS

スクロール連動部分を分かりやすくするため、その他デザインは単純な仕様とします。スクロール連動アクションについても、今回は該当するメニューの背景色を変更するだけにします。

#indexList a.active {
    background-color: orange;
}

Javascript

まずは全体を記述します。大まかなイメージとしては、ウィンドウのスクロール値を取得して、お目当てのセクションまでスクロールされれば、リンクするナビメニューにcssクラスをつける、といった流れになります。

$(function () {
    $(window).on("load scroll resize", function () {

    let scrolll = $(window).scrollTop();
    let windowHeight= $(window).height();

    $('.box').each(function () {
        let target = $(this).offset().top;
        let idName = $(this).attr("id");

        if (scroll > target - windowHeight + (windowHeight / 2)) {
            $("#indexList a").removeClass("active");
            let link = $("#indexList a[href *= " + idName +"]");
            $(link).addClass("active");
            }
        });
    });
});

+α intersection observer

intersection observerというAPIで実装したものです。jQueryが主に画面スクロールをトリガーにして動いていたのに対して、こちらは対象のセクションが画面端に交差したことをトリガーに動きます。

jQueryと違い、何度もスクロール値を取得することがないので、その分動きが軽くなります。

サンプルページ02(PC専用)>>
// 交差を監視する要素を配列の中にセット
const boxes = document.querySelectorAll(".box");

// Intersection Observerの設定
const options = {
    root: null,
    rootMargin: "0px",
    threshold: 0.5
};

// Intersection Observerを使えるようにする
const observer = new IntersectionObserver(intersect, options);

// 対象(準備した配列内)の要素をそれぞれ監視する
boxes.forEach(box => {
    observer.observe(box);
});

// 交差したときに実行する関数
function intersect(entries) {
    entries.forEach(entry => {
        if (entry.isIntersecting) { // 監視中の要素が交差した状態ならtrueになる
            // 監視中の要素が交差したときの処理
            activateIndex(entry.target);
        }
    });
}

// メニューの色を変える関数
function activateIndex(element) {
// すでにアクティブになっている目次を選択
const currentActiveIndex = document.querySelector("#indexList .active");
// すでにアクティブになっているものが0個の時(=null)以外は、activeクラスを除去
if (currentActiveIndex !== null) {
    currentActiveIndex.classList.remove("active");
}
// 引数で渡されたDOMが飛び先のaタグを選択し、activeクラスを付与
const newActiveIndex = document.querySelector(`a[href='#${element.id}']`);
    newActiveIndex.classList.add("active");
}