[jQuery]スクロールに連動して目次をアクティブにする
ユーザーに対して表示中のコンテンツを見える化する
サイトの構成には様々あり、中には目次を常に表示しているサイトも存在します。
目次を常に表示する意図としてはコンテンツが多岐に渡るためガイドを目的として設置されていたり、目的の内容へジャンプするためのリンクであったりと、どちらもユーザーに配慮したものとなっています。
更に欲を言えばどの目次の内容を表示しているかひと目で分かることができれば助かりますよね。
そこで次の機能を実装したいと思います。
- 目次を画面に固定表示する
- コンテンツが表示中か否か判定
- 対応する目次に対して文字色とフォントサイズを変更する
See the Pen scroll-point by nanase webdesigner (@nanase-777) on CodePen.
コンテンツの用意
高さの異なるボックス(box1~4
)を用意します。.js-box
というクラスはjQueryで制御するためのクラスということで頭に「js
」を付けて区別しています。
文字色とフォントサイズを変更したい目次に対しては.active
というcssを追加します。
目次のol
要素をposition:fixed;
で固定表示しています。中身のli
要素はjQuery側で追加するので空白です。
ボックス数に合わせてli要素を作成
1 2 3 4 |
$('.js-box').each(function() { var title = $(this).find('h2').text(); // ボックス内の見出しを抜き出す $('ol').append('<li>' + title + '</li>'); }); |
目次を手作業でコーディングする方法もありますが、管理しやすくするためにボックスの内容を元に自動で作成されるようにしたいと思います。
「ボックスの見出し」=「目次の見出し」にするため、text()
でボックスの見出しのテキストを抜き出します。
そしてテキストをli
要素に収め、append()
で親要素であるol
要素へ追加していきます。
コンテンツが表示中か否かの判定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
if (scroll < elPos - (windowHeight / 2)) { // ウインドウより下部に位置しているとき $('li').eq(index).removeClass('active'); } else { // ウインドウ内部~上部に位置しているとき if (scroll < nextElPos - (windowHeight / 2)) { // 次の要素がウインドウ上に現れていない場合 $('li').eq(index).addClass('active'); } else { // 次の要素がウインドウ上に現れた場合 $('li').eq(index).removeClass('active'); } } |
ボックスがウィンドウに表示された場合は対応する目次のli
要素に.active
を追加し、表示されなくなった場合は.active
を取り除きます。
.active
を取り除く条件ですが、「スクロールがウィンドウ上部へ通り過ぎた場合」「次のボックスが表示された場合」なので各タイミングで.active
を取り除きます。
どのli
要素へ.active
を追加するかですが、まずボックスが何番目の要素かを$(this).index()
でカウントします。そしてカウントした順番をli
要素に対してeq()
で指定することで対応可能です。
※厳密には画面半分の位置(windowHeight/2
)を境に判定しています。
次の要素のY座標について
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$('.js-box').each(function(i) { i += 1; // 何番目の要素かカウント。(1~n) // ~ 省略 ~ nextElPos = $(document).height(); if (i != $('.js-box').length) { // 最後の要素でない場合 // 次の要素の座標を設定 nextElPos = $(this).next().offset().top; } // ~ 省略 ~ }); |
最後尾のボックスは次のボックスの座標を取得できません。そこで代わりとしてサイト全体の高さ($(document).height()
)を渡すことで「ウインドウ内である」という判定にします。
最後尾か否かはeach(function(i){})
のインデックスi
を利用します。インデックスがボックスの数と一致すれば最後尾となります。注意点としてインデックスは0からカウントするので、事前に+1
しておきます。
以上でスクロールに連動して目次をアクティブにする機能が実装できました。