スクロール位置に応じてナビをハイライトする Scroll Spy UI の作り方

Scroll Spy UIのアイキャッチ画像

長いページで「今どこを読んでいるのか分かるUI」見たことありませんか?

  • ドキュメントサイト
  • LP(ランディングページ)
  • ブログの目次

こういったUIでは、スクロールに応じてナビゲーションが自動で切り替わります。

これが Scroll Spy UI です。

この記事では、JavaScriptとIntersectionObserverを使って
シンプルで実用的なScroll Spyを作ります。

Scroll Spyはスクロール位置を検知して動作するUIです。

スクロール検知の基本については
Scroll Trigger Animation
で解説しています。

1.完成イメージ

  • 左:ナビゲーション(現在位置がハイライト)
  • 右:コンテンツ
  • スクロールで自動更新
  • クリックでスムーススクロール

2.実装コード(コピペOK)

HTML

<div class="container">
  <nav class="nav">
    <a href="#section1" class="nav-item active">Section 1</a>
    <a href="#section2" class="nav-item">Section 2</a>
    <a href="#section3" class="nav-item">Section 3</a>
    <a href="#section4" class="nav-item">Section 4</a>
  </nav>

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

CSS

body {
  margin: 0;
  font-family: sans-serif;
}

.container {
  display: flex;
}

.nav {
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 20px;
  background: #111;
  display: flex;
  flex-direction: column;
}

.nav-item {
  color: #888;
  text-decoration: none;
  margin-bottom: 10px;
  transition: 0.3s;
}

.nav-item.active {
  color: #fff;
  font-weight: bold;
}

.content {
  flex: 1;
}

.section {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  border-bottom: 1px solid #eee;
}

JavaScript

const sections = document.querySelectorAll(".section");
const navItems = document.querySelectorAll(".nav-item");

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        navItems.forEach((item) => item.classList.remove("active"));

        const id = entry.target.id;
        const activeItem = document.querySelector(`.nav-item[href="#${id}"]`);

        if (activeItem) {
          activeItem.classList.add("active");
        }
      }
    });
  },
  {
    threshold: 0.6,
  }
);

sections.forEach((section) => observer.observe(section));

スムーススクロール(任意)

「スムーススクロール」は、ページ内リンクをクリックしたときに
一瞬でジャンプするのではなく、なめらかに移動する挙動のことです。

html {
  scroll-behavior: smooth;
}

このようなスクロール連動UIは、
Scroll Story UI
のようなストーリー型レイアウトにも応用できます。

スクロールによる変化のタイミングは、
Scroll Trigger Animation
と比較すると理解しやすいです。

3.実験:Scroll Spyの動きを観察する

スクロールするとナビがどのタイミングで切り替わるか確認してみましょう。

観察ポイント

  • どの位置でハイライトが切り替わるか
  • スクロール速度による違い
  • 複数セクションが重なったときの挙動

4.よくある問題

①ハイライトが頻繁に切り替わる

👉 threshold を調整

threshold: 0.6

②意図しないセクションがアクティブになる

👉 セクション高さ or margin の影響

③スクロール位置とズレる

👉 rootMargin を使うと調整可能

rootMargin: "-20% 0px -40% 0px"

5.解説ポイント

IntersectionObserverを使う理由

  • スクロールイベントより軽い
  • パフォーマンス良い
  • 実務でもよく使う

スクロール連動UIは他にもあり、
Sticky Scroll Animation
のように位置を固定して演出するパターンもあります。

6.まとめ

  • Scroll Spyは「現在位置を可視化するUI」
  • IntersectionObserverで簡単に実装できる
  • thresholdで挙動調整が重要

Scroll Animationシリーズ

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA