スムーズスクロールとセクションナビゲーションの実装方法とその利点[CSS+javascript]

CSS、JavaScript

スムーズスクロールとセクションナビゲーションを実装する方法について紹介します。

スムーズスクロールを有効にすることで、ユーザーがページ内をスムーズに移動できるようになります。また、現在のセクション番号と合計セクション数を表示し、最後のセクションに到達した場合にはトップへ戻るボタンを表示する機能も組み込んでいますので興味のある方はご参考ください!

サンプル

See the Pen test_Scroll by kasasagi_kmnmc (@kasasagi_kmnmc) on CodePen.

画面右下に「Scroll Down」というリンクが表示されます。
こちらをクリックすると、各セクションへ遷移されます。
また、ページ下部までスクロールされると「Scroll Top」に変わり、こちらをクリックするとページの先頭へ戻ることが出来ます。

HTML

<div class="section" id="section1">
    <h1>Section 1</h1>
</div>
<div class="section" id="section2">
    <h1>Section 2</h1>
</div>
<div class="section" id="section3">
    <h1>Section 3</h1>
</div>

<div class="scroll-info" id="scrollInfo">
    <span id="currentSectionNumber">1</span> / <span id="totalSections">3</span> Sections
</div>

<div class="scroll-down" id="scrollDown" data-action="down">
    <span>Scroll Down</span>
    <div class="arrow">↓</div>
</div>

このコードでは、各セクションが<div>要素として定義されています。例えば、以下のようになっています。

<div class="section" id="section1">
    <h1>Section 1</h1>
</div>

各セクションには固有のIDが付与され、それぞれ異なる背景色が設定されています(例えば#section1は#ffccccの背景色を持ちます)。これにより、ページの異なるセクションが視覚的に区別されやすくなります。

CSS

body, html {
    margin: 0;
    padding: 0;
    scroll-behavior: smooth;
}

.section {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 3em;
    scroll-margin-top: 50px;
}

#section1 {
    background-color: #ffcccc;
}

#section2 {
    background-color: #ccffcc;
}

#section3 {
    background-color: #ccccff;
}

.scroll-info {
    position: fixed;
    top: 20px;
    right: 20px;
    background-color: rgba(255, 255, 255, 0.8);
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    font-size: 1.2em;
}

.scroll-down {
    position: fixed;
    bottom: 20px;
    right: 20px;
    cursor: pointer;
    text-align: center;
    font-size: 1.2em;
    z-index: 1000;
}

.scroll-down .arrow {
    font-size: 2em;
    margin-top: 5px;
}

CSSでは、セクション全体のスタイルが定義されています。例えば、以下のように設定されています。

.section {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 3em;
    scroll-margin-top: 50px;
}

これにより、各セクションが画面全体の高さを占め、中央に配置されるようになっています。また、スクロール時の位置調整(scroll-margin-top: 50px;)も行われています。

JavaScript

document.addEventListener('DOMContentLoaded', function () {
    const scrollDownButton = document.getElementById('scrollDown');
    const sections = document.querySelectorAll('.section');
    const currentSectionNumberElement = document.getElementById('currentSectionNumber');
    const totalSectionsElement = document.getElementById('totalSections');
    let currentSectionIndex = 0;

    totalSectionsElement.textContent = sections.length;

    function scrollToSection(index) {
        const section = sections[index];
        const offset = section.offsetTop;
        window.scrollTo({ top: offset, behavior: 'smooth' });
    }

    function updateButton() {
        sections.forEach((section, index) => {
            const rect = section.getBoundingClientRect();
            if (rect.top <= window.innerHeight / 2 && rect.bottom >= window.innerHeight / 2) {
                currentSectionIndex = index;
            }
        });

        currentSectionNumberElement.textContent = currentSectionIndex + 1;

        const lastSection = sections[sections.length - 1];
        const lastSectionRect = lastSection.getBoundingClientRect();

        if (lastSectionRect.bottom <= window.innerHeight && currentSectionIndex === sections.length - 1) {
            scrollDownButton.innerHTML = '<span>Scroll Top</span><div class="arrow">↑</div>';
            scrollDownButton.dataset.action = 'up';
            scrollDownButton.onclick = () => window.scrollTo({ top: 0, behavior: 'smooth' });
        } else {
            scrollDownButton.innerHTML = '<span>Scroll Down</span><div class="arrow">↓</div>';
            scrollDownButton.dataset.action = 'down';
            scrollDownButton.onclick = () => {
                if (currentSectionIndex < sections.length - 1) {
                    scrollToSection(currentSectionIndex + 1);
                } else {
                    scrollToSection(currentSectionIndex);
                }
            };
        }

        scrollDownButton.classList.toggle('visible', lastSectionRect.bottom <= window.innerHeight);
    }

    document.addEventListener('scroll', updateButton);
    updateButton();
});

JavaScriptでは、スムーズスクロールとセクションのナビゲーションが実装されています。以下の機能が特に重要です。

スムーズスクロールの実装

function scrollToSection(index) {
    const section = sections[index];
    const offset = section.offsetTop;
    window.scrollTo({ top: offset, behavior: 'smooth' });
}

この関数は、指定されたセクションの位置までスムーズにスクロールする機能を提供します。「window.scrollTo」の第一引数で指定されたtopには、対象セクションの「offsetTop」が指定されており、「behavior: ‘smooth’」によってスムーズなスクロールが実現されます。

現在のセクションの更新と表示

function updateButton() {
    sections.forEach((section, index) => {
        const rect = section.getBoundingClientRect();
        if (rect.top <= window.innerHeight / 2 && rect.bottom >= window.innerHeight / 2) {
            currentSectionIndex = index;
        }
    });

    currentSectionNumberElement.textContent = currentSectionIndex + 1;
}

updateButton」関数は、現在表示されているセクションのインデックスを検出し、それを基に現在のセクション番号を表示します。各セクションの位置情報を取得して比較し、画面の中央付近に表示されているセクションを「currentSectionIndex」として設定します。これにより、ユーザーは現在どのセクションにいるかが分かりやすくなります。

ページ末尾でのトップへ戻るボタンの表示

if (lastSectionRect.bottom <= window.innerHeight && currentSectionIndex === sections.length - 1) {
    scrollDownButton.innerHTML = '<span>Scroll Top</span><div class="arrow">↑</div>';
    scrollDownButton.dataset.action = 'up';
    scrollDownButton.onclick = () => window.scrollTo({ top: 0, behavior: 'smooth' });
} else {
    scrollDownButton.innerHTML = '<span>Scroll Down</span><div class="arrow">↓</div>';
    scrollDownButton.dataset.action = 'down';
    scrollDownButton.onclick = () => {
        if (currentSectionIndex < sections.length - 1) {
            scrollToSection(currentSectionIndex + 1);
        } else {
            scrollToSection(currentSectionIndex);
        }
    };
}

この部分では、ページの最後までスクロールした場合にトップへ戻るボタンを表示するかどうかを制御しています。

「lastSectionRect.bottom <= window.innerHeight」が条件となり、かつ「currentSectionIndex === sections.length – 1」のとき、ページの最後のセクションに到達していることを確認します。

この場合、ボタンのテキストとアイコンが「Scroll Top」および「↑」に変更され、クリック時にページのトップまでスムーズにスクロールします。

メリットとデメリット

メリット

  • ユーザーエクスペリエンスの向上:
    ユーザーはスムーズなスクロールにより快適にページ内を移動できます。
  • 視覚的なインジケーション
    現在のセクション番号やトップへ戻るボタンの表示により、ユーザーにとってページのナビゲーションが明確になります。

デメリット

  • JavaScriptの依存
    スムーズスクロールやセクションナビゲーションを実現するためにJavaScriptが必要です。JavaScriptが無効な環境では正しく機能しない可能性があります。
  • パフォーマンスの影響
    大量のセクションや複雑なJavaScript処理がページの読み込みやレンダリングに影響を与える場合があります。

注意点

  • クロスブラウザの動作確認
    スムーズスクロールやセクションナビゲーションの動作はブラウザに依存する場合があります。異なるブラウザやデバイスでの動作をテストして確認することが重要です。
  • アクセシビリティの配慮
    JavaScriptに依存せず、セクションへのナビゲーションが適切に行えるように、適切なHTML構造とセマンティクスを保つことが推奨されます。

まとめ

いかがでしたか?
今回はスムーズスクロールとセクションナビゲーションを実装する方法について紹介しました。

この実装は、ウェブページのナビゲーションを改善し、ユーザーエクスペリエンスを向上させるための有力な手段です。スムーズなスクロールと視覚的なインジケーションにより、ユーザーはページのコンテンツに集中しやすくなります。

ただし、JavaScriptの依存やパフォーマンスの影響、クロスブラウザの対応などに留意する必要がありますのでご注意ください!

タイトルとURLをコピーしました