【SWELL】サイドバーの目次をハイライト表示させる方法(いま表示している位置がわかる)

広告:ページ内にてアフィリエイト広告を利用しています。

目次の現在位置をハイライト表示する方法

SWELL では、標準で「目次」を表示する機能があります。

とても便利な機能で、サイドバーにも目次を表示することができますが、今自分が表示している位置がハイライトで表示されているともっとわかりやすくて便利になりますね。

ポイント

本記事では、

サイドバーの目次の現在位置をハイライトする方法を紹介します。

かっこいいページにしていきましょう。

SWELL おすすめサンプルページ
おしゃれサイト

\SWELL でオシャレサイトを作る方法は こちら をクリックしてください/

目次
PR

目次の現在位置をハイライトしたサンプル

実際にハイライトしたサンプルです。

左側の本文で表示している見出しに合わせて、右側のサイドバーの目次の該当部分をハイライト表示しています。本サイトでも実装しているので動きを参考にしてください。

目次の現在位置をハイライトする方法

目次の現在位置をハイライトするには、JavaScript と CSS を利用します。

JavaScript は対象となる記事全ページに適用させる必要があり、いくつか実装方法がありますので、あわせて紹介します。

■ 実装するコード(JavaScript)

実装するJavaScript を紹介します。

実装する JavaScript はこちら

var varHtagElements = null;
var varHtagPosition = null;
var varSideBarItem = null;

window.addEventListener('load', function () {
    setTimeout(function(){fnAfterContents();}, 10);
});

function fnAfterContents() {
    // H2、H3 を全て取得する(位置を計算する)
    varHtagElements = document.querySelectorAll('h2, h3');
    var varHtagArray = Array.from(varHtagElements);
    var varHtagPosition = varHtagArray.map(item => item.getBoundingClientRect().top);
    var varHtagPositionWithScroll = varHtagPosition.map(top => Math.floor(top + window.scrollY));
	
    // サイドバーの目次のリストを取得する
    varSideBarItem = document.querySelectorAll('#sidebar .p-toc__link');
  
    if (varSideBarItem == null || varSideBarItem.length == 0) {
        // 目次が無ければ終了
        return;
    }

    // 個数を取得
    const countHtag = varHtagElements.length;
    const countSideBarItem = varSideBarItem.length;
    const iMaxLoop = countHtag > countSideBarItem ? countSideBarItem : countHtag;

    window.addEventListener('scroll', () => {
        // 計算する位置
        const currentPosition = window.scrollY + 300;

        for (let iCount = 0; iCount < iMaxLoop; iCount++) {
            // 現在位置の表示を消す
            varSideBarItem[iCount].classList.remove('currentTocPosition');
            if (iCount >= iMaxLoop - 1 ) {
                // 要素の最後は、次の要素が無いので範囲外のみ判定
                if (currentPosition >= varHtagPositionWithScroll[iCount]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                }
            } else {
                // 要素の途中は、範囲内かどうかを判定
                if (currentPosition >= varHtagPositionWithScroll[iCount] && currentPosition < varHtagPositionWithScroll[iCount + 1]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                } 
            }
        }
    });
}

ちょっと長いですね。軽くポイントを説明します。

「JavaScript の中身に興味はないので早く実装方法を知りたい」という方は飛ばして次の章に進んでください。

JavaScript のポイント

ポイント
  • 「querySelectorAll(‘h2, h3’);」で本文中の H2 と H3 を取得しています

→ 目次で H4 や H5 まで表示している方は ‘h2, h3’ にカンマ区切りで h4 や h5 を足してください。

ポイント
  • 「window.scrollY + 300;」で本文中の表示位置の計算上の数値を調整しています

→ 300 を足さないと、見出しが画面上部に表れた瞬間にハイライトが移ってしまい、実際の操作に対して違和感がでますので、300を足して、スクロール操作との違和感を調整しています。あれ?と思ったら数字を変えてください。

ポイント
  • 「#sidebar .p-toc__link」が SWELL の目次のクラスです

→ 今後の SWELL のアップデート等でクラス名が変わる可能性もありますので動かなくなったらご確認ください。

ポイント
  • 「classList.add(‘currentTocPosition’);」で現在位置の目次にクラス名を付与する

→ 計算した結果現在位置と思われる目次の項目にクラス名を付けています。

以降は実際に SWELL で実装する方法です。全記事に反映させるためには、いくつか方法がありますので、ご自身のよりわかりやすい方法で実装してください。(どの方法を使っても結果は一緒です)

■(方法.1)functions.php に記載する

functions.php に記載して各記事に強制的に JavaScript を追記する方法です。

対応が簡単ですが、誤った場合にリスクの大きい方法です。

注意

functions.php は不正なコードを記載するとサイトが一切表示できなくなるなど影響が大きいため、必ずバックアップを取るなどで注意して対応してください。

WordPress の管理画面から、「外観」→「テーマファイルエディター」を選択する。

「テーマファイルエディター」
  • 「テーマのための関数(funtions.php)」を選択する
  • コードを設定する

設定するコードは下記です。(JavaScript の前後に出力用の php を追記しています)

//------------------------------------------------------
// サイドバーの目次をハイライトする
//------------------------------------------------------
function highlight_toc() {
    if (is_single()) {
        ?>
<script>
var varHtagElements = null;
var varHtagPosition = null;
var varSideBarItem = null;

window.addEventListener('load', function () {
    setTimeout(function(){fnAfterContents();}, 10);
});

function fnAfterContents() {
    // H2、H3 を全て取得する(位置を計算する)
    varHtagElements = document.querySelectorAll('h2, h3');
    var varHtagArray = Array.from(varHtagElements);
    var varHtagPosition = varHtagArray.map(item => item.getBoundingClientRect().top);
    var varHtagPositionWithScroll = varHtagPosition.map(top => Math.floor(top + window.scrollY));
	
    // サイドバーの目次のリストを取得する
    varSideBarItem = document.querySelectorAll('#sidebar .p-toc__link');
  
    if (varSideBarItem == null || varSideBarItem.length == 0) {
        // 目次が無ければ終了
        return;
    }

    // 個数を取得
    const countHtag = varHtagElements.length;
    const countSideBarItem = varSideBarItem.length;
    const iMaxLoop = countHtag > countSideBarItem ? countSideBarItem : countHtag;

    window.addEventListener('scroll', () => {
        // 計算する位置
        const currentPosition = window.scrollY + 300;

        for (let iCount = 0; iCount < iMaxLoop; iCount++) {
            // 現在位置の表示を消す
            varSideBarItem[iCount].classList.remove('currentTocPosition');
            if (iCount >= iMaxLoop - 1 ) {
                // 要素の最後は、次の要素が無いので範囲外のみ判定
                if (currentPosition >= varHtagPositionWithScroll[iCount]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                }
            } else {
                // 要素の途中は、範囲内かどうかを判定
                if (currentPosition >= varHtagPositionWithScroll[iCount] && currentPosition < varHtagPositionWithScroll[iCount + 1]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                } 
            }
        }
    });
}
</script>
        <?php
    }
}
add_action('wp_footer', 'highlight_toc');

前述の JavaScript に対して赤字の部分が追加になっていますのでご注意ください。

ポイント

is_single() を用いて投稿記事のみ対象にしています。

■(方法.2)「bodyタグ終了直前に出力するコード」に記載する

SWELL は記事内の各所にコードを追記できるよう準備されていますので、「bodyタグ終了直前に出力するコード」に JavaScript を記載する方法もあります。

「入力エリアが小さくて見てわかりにくい」、「他にも追加したいときにごちゃごちゃになりやすい」的なデメリットもありますが、比較的安全かつ簡単な方法です。

WordPress の管理画面から「外観」→「カスタマイズ」→「高度な設定」を選択します。

「bodyタグ終了直前に出力するコード」
  • コードを設定する

設定するコードは下記です。

<script>
var varHtagElements = null;
var varHtagPosition = null;
var varSideBarItem = null;

window.addEventListener('load', function () {
    setTimeout(function(){fnAfterContents();}, 10);
});

function fnAfterContents() {
    // H2、H3 を全て取得する(位置を計算する)
    varHtagElements = document.querySelectorAll('h2, h3');
    var varHtagArray = Array.from(varHtagElements);
    var varHtagPosition = varHtagArray.map(item => item.getBoundingClientRect().top);
    var varHtagPositionWithScroll = varHtagPosition.map(top => Math.floor(top + window.scrollY));
	
    // サイドバーの目次のリストを取得する
    varSideBarItem = document.querySelectorAll('#sidebar .p-toc__link');
  
    if (varSideBarItem == null || varSideBarItem.length == 0) {
        // 目次が無ければ終了
        return;
    }

    // 個数を取得
    const countHtag = varHtagElements.length;
    const countSideBarItem = varSideBarItem.length;
    const iMaxLoop = countHtag > countSideBarItem ? countSideBarItem : countHtag;

    window.addEventListener('scroll', () => {
        // 計算する位置
        const currentPosition = window.scrollY + 300;

        for (let iCount = 0; iCount < iMaxLoop; iCount++) {
            // 現在位置の表示を消す
            varSideBarItem[iCount].classList.remove('currentTocPosition');
            if (iCount >= iMaxLoop - 1 ) {
                // 要素の最後は、次の要素が無いので範囲外のみ判定
                if (currentPosition >= varHtagPositionWithScroll[iCount]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                }
            } else {
                // 要素の途中は、範囲内かどうかを判定
                if (currentPosition >= varHtagPositionWithScroll[iCount] && currentPosition < varHtagPositionWithScroll[iCount + 1]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                } 
            }
        }
    });
}
</script>

前述の JavaScript に対して赤字の部分が追加になっていますのでご注意ください。

■(方法.3)ブログパーツを使って各記事に張り付ける

SWELL には「ブログパーツ」というコンテンツを各記事で共有できる便利な機能があります。ブログパーツを使うのも一つの方法です。

各記事に張り付ける手間がかかりますが、最も安全で個人的には一番気に入っている方法です。(私見です)

Step.1. WordPress の管理画面から「ブログパーツ」を選択し、新規作成します。

ブログパーツ作成画面
  • 「カスタムHTML」ブロックを配置する
  • コードを設定する

設定するコードは下記です。(方法2と同じコードです)

<script>
var varHtagElements = null;
var varHtagPosition = null;
var varSideBarItem = null;

window.addEventListener('load', function () {
    setTimeout(function(){fnAfterContents();}, 10);
});

function fnAfterContents() {
    // H2、H3 を全て取得する(位置を計算する)
    varHtagElements = document.querySelectorAll('h2, h3');
    var varHtagArray = Array.from(varHtagElements);
    var varHtagPosition = varHtagArray.map(item => item.getBoundingClientRect().top);
    var varHtagPositionWithScroll = varHtagPosition.map(top => Math.floor(top + window.scrollY));
	
    // サイドバーの目次のリストを取得する
    varSideBarItem = document.querySelectorAll('#sidebar .p-toc__link');
  
    if (varSideBarItem == null || varSideBarItem.length == 0) {
        // 目次が無ければ終了
        return;
    }

    // 個数を取得
    const countHtag = varHtagElements.length;
    const countSideBarItem = varSideBarItem.length;
    const iMaxLoop = countHtag > countSideBarItem ? countSideBarItem : countHtag;

    window.addEventListener('scroll', () => {
        // 計算する位置
        const currentPosition = window.scrollY + 300;

        for (let iCount = 0; iCount < iMaxLoop; iCount++) {
            // 現在位置の表示を消す
            varSideBarItem[iCount].classList.remove('currentTocPosition');
            if (iCount >= iMaxLoop - 1 ) {
                // 要素の最後は、次の要素が無いので範囲外のみ判定
                if (currentPosition >= varHtagPositionWithScroll[iCount]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                }
            } else {
                // 要素の途中は、範囲内かどうかを判定
                if (currentPosition >= varHtagPositionWithScroll[iCount] && currentPosition < varHtagPositionWithScroll[iCount + 1]) {
                    varSideBarItem[iCount].classList.add('currentTocPosition');
                } 
            }
        }
    });
}
</script>

前述の JavaScript に対して赤字の部分が追加になっていますのでご注意ください。

Step.2. 各記事の最後にブログパーツのショートコードを張り付ける

ちょっと手間ですけど、各記事の最後(今後記事を作成する場合も毎回)、ブログパーツのショートコードを配置します。目次のハイライト機能を適用したい記事のみに貼り付けます。

ブログパーツのショートコードを張り付ける
  • 作成したブログパーツのショートコードを設定する

方法1,2,3のどれを用いても結果は同じになりますので、使い勝手が良い方法で実装してください。

■ 実装するコード(CSS)

実際にハイライトする見た目(背景色など)をCSSで実装します。

CSSは、WordPress の管理画面から「外観」→「カスタマイズ」→「追加CSS」に設定します。

CSSを設定する画面
  • CSSを設定する

設定するコードは下記です。(方法2と同じコードです)

.p-toc__link.currentTocPosition {
  background-color: #FADCE9 !important;
}

「#FADCE9」の部分が色を指定しており、この値では赤系(ピンク)になります。

主な色は以下の通り。

#FEECD2
#FFFCDB
#D3EDFB
#FADCE9
#ECF4D9

その他、色を参考にしたい方は以下の記事を参照してください。

背景全部ではなく、下線蛍光マーカーにしたい場合

上図のように、下線蛍光マーカーにしたい場合は、CSSを変えることで可能です、次のCSSにしてください。

.p-toc__link.currentTocPosition {
  background: linear-gradient(transparent 40%, #FADCE9 50%);
}

同じく、色を変えたい場合は、「#FADCE9」の値を変えます。

まとめ:目次の現在位置をハイライトする方法

SWELLで目次の現在位置をハイライトする方法を紹介しました。

現在位置の取得は JavaScript で行い、ハイライト表示はCSSで設定します。記事全部に適用する場合にはいくつかの方法があり、自分にとってより良い方法を利用すると良いでしょう。

ぜひ、すてきなサイトを作ってくださいね。

SWELL おしゃれサイト作り方

SWELL の利用方法などについてココナラにて「支援作業」を販売しております。

よかったらご利用くださいませ。

PR

PR

一番上に戻る(Back to the initial position on click.)

トップページ(Home.)

PR
Amazon でお買い物
楽天市場でお買い物
広告の設置・収入について

当サイトは Amazonのアソシエイトとして、適格販売により収入を得ています。

当サイトは Google アドセンスを利用し、広告により収入を得ています。

当サイトは ASP が提供するサービスを利用し、広告、適格販売により収入を得ています。

電気通信事業法改正に伴う表記

この記事が気に入ったら
フォローしてね!

目次