目次
はじめに
「目次」ウィジェットを「サイドバースクロール追従」に配置し、現在表示されている見出しの位置に対応する目次項目をハイライト表示させます。
この記事では、この方法について説明します。
完成イメージ

実装方法
以下に手順で実装します。
- ラベルJavascriptを追加
以下のコードをjavascript.jsに追加します。
jQuery(function ($) { // サイドバー内にある目次ウィジェットのすべてのリンクを取得 const $tocs = $('.sidebar-scroll .widget_toc a'); // スクロール位置の判定時に用いるオフセット値 const offset = 50; // 本文中の各見出しの識別子(ID)と位置座標を格納するための配列 let headerPositions = []; /** * 文中の各見出しの位置(上からの座標)を計算して記憶 * * @return {void} */ function cachePositions() { headerPositions = $('.entry-content :header span').map(function () { const $el = $(this); return { id: $el.attr('id'), top: $el.offset().top - offset }; }).get(); } /** * 現在のスクロール位置に対応する目次リンクの表示を更新 * * @return {void} */ function highlight() { const scrollTop = $(window).scrollTop(); let currentId = ''; // 上から順に見出しの位置をチェックし、現在のスクロール位置がどの見出しを通過しているかを判定 for (let i = 0; i < headerPositions.length; i++) { if (scrollTop >= headerPositions[i].top) { currentId = headerPositions[i].id; } else { break; } } // 該当する見出しのIDが見つかった場合、既存のハイライトを外して対象の目次リンクに .currentを付与 if (currentId) { $tocs.removeClass('current'); $tocs.filter(`[href="#${currentId}"]`).addClass('current'); } } // 目次リンクが存在する場合 if ($tocs.length) { cachePositions(); highlight(); // ページスクロールの場合 $(window).on('scroll', () => { requestAnimationFrame(highlight); }); // ページリサイズの場合 let resizeTimer; $(window).on('resize', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { cachePositions(); highlight(); }, 200); }); // 「アコーディオン」ブロックなどの開閉による.main要素のサイズ変化を監視し、変化時に位置を再計算 const mainElement = document.querySelector('.main'); if (mainElement) { const resizeObserver = new ResizeObserver(() => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { cachePositions(); highlight(); }, 100); }); resizeObserver.observe(mainElement); } } }); - ラベルCSSを追加
以下のコードをstyle.cssに追加する。
.sidebar-scroll .toc-list a.current { background-color: #ff0000; }

