LoginSignup
9
10

More than 1 year has passed since last update.

ページ内ナビゲーションの現在地の表示は IntersectionObserver を使うと良さそう

Posted at

ここ最近、ウェブページ内ナビゲーションの現在地の表示(カレント表示)を実装する時は IntersectionObserver を使っています。
以前はスクロールイベントで位置を取って計算していましたが、 IntersectionObserver を使った方が簡単に実装できる上、パフォーマンスの観点でも良いとのことなので、使い方をメモしておきます。

サンプルのデモはこちら

サンプルの解説

<div class="nav">
  <ul>
    <li><a class="navBtn" href="#section1">section1</a></li>
    <li><a class="navBtn" href="#section2">section2</a></li>
    <li><a class="navBtn" href="#section3">section3</a></li>
  </ul>
</div>

<div id="section1" class="section">section1</div>
<div id="section2" class="section">section2</div>
<div id="section3" class="section">section3</div>
const ACTIVE_CLASS_NAME = 'active';
const buttons = document.querySelectorAll('.navBtn');

buttons.forEach(button => {
  const target = document.querySelector(button.getAttribute('href'));
  const observer = new IntersectionObserver(([{isIntersecting}]) => {
    if (isIntersecting) {
      buttons.forEach(el => el.classList.remove(ACTIVE_CLASS_NAME));
      button.classList.add(ACTIVE_CLASS_NAME);
    }
  });
  observer.observe(target);
})
  1. それぞれのナビのボタンの href 属性から、ターゲットの要素(この例だと #section1, #section2, #section3)を取得します。
  2. new IntersectionObserver でコンストラクターを呼び出し、オブザーバーを作成します。
  3. オブザーバーのコールバックとして、ボタンの現在地の表示を切り替える処理を渡します。このコールバックは、画面内にターゲットが見えるようになった時と、見えなくなった時の両方で呼ばれます。見えるようになった時のみに処理が走るように、 isIntersecting を条件に加えます。
  4. あとは、監視するターゲット要素を与えてあげるだけです!

ちなみに、どの時点で画面に入ったとするかのタイミング(しきい値)なども、オプションで自由度高くコントロールできてとても便利です。

以上!

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10