WordPress にプラグインを使わずに JavaScript だけで目次機能をつけてみた

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

目次機能が出来るプラグインとかってあるけど、別に自分で作ってもいいよねって思ったので作った。そのうちモリモリっとテーマやプラグインの整備に力を入れていくので、そのあたりに介入されると困るので~~ってくらいの理由で作った次第。

これこれ!この目次! h2 タグを使うんだよ

2階層までなら対応するよ! h3 タグだよ

ここは h3 タグ

ここは h2 タグなので 1 階層目になる

ここは 2 階層。 h3 タグだからね

デモおわり

ここまで見出しだらけで見にくいのは仕方ない。

仕組み

  1. h2 タグと h3 タグを投稿箇所から探す
  2. それぞれのタグに ID をつける
  3. それぞれへのリンクを生成する
  4. 目次用の HTML を作る
  5. 一番最初の見出しの直前に HTML を挿入する

タイトルこそ WordPress って言ってるけど JavaScript が差し込めるブログサービス的なものなら、投稿箇所を探す部分を調整する必要はあるけど、どれでもできるんじゃないかな。
jQuery を使わなくていいように作ったので jQuery ないんだけど、みたいな環境でもいいと思う。いやそもそもそういう環境はまた違う問題っぽいけど…。

JavaScript

(function() {
    setTimeout(function() {
        var headingIndex = 1;
        Array.prototype.forEach.call(document.querySelectorAll('.post_content'), function(postContent) {
            if (postContent.innerText.length < 100) {
                return;
            }

            var headings = postContent.querySelectorAll('h2,h3');
            if (headings.length <= 0) {
                return;
            }

            var indexHtml = '<ul>';
            var lastElement = 'H2';
            Array.prototype.forEach.call(headings, function(e) {
                var id = 'heading-' + headingIndex;
                e.id = id;
                if (lastElement != e.tagName) {
                    if (lastElement == 'H2') {
                        indexHtml += '<ul>';
                    } else {
                        indexHtml += '</ul>';
                    }
                    lastElement = e.tagName;
                }
                indexHtml += '<li><a href="#' + id + '">' + e.innerHTML + '</a></li>';
                headingIndex++;
            });
            indexHtml += '</ul>';

            var wrapper = document.createElement('div');
            wrapper.classList.add('content-index');
            wrapper.innerHTML = indexHtml;
            headings[0].parentNode.insertBefore(wrapper, headings[0]);
        });

        if (location.hash.length > 1) {
            setTimeout(function() {
                var element = document.querySelector(location.hash);
                if (element != null) {
                    window.scroll(0, element.offsetTop);
                }
            }, 10);
        }
    }, 10);
})();

CSS

.post_content .content-index {
	border: 2px solid #eee;
	border-radius: 20px;
	padding: 20px;
	background-color: #fefefe;
}

.post_content .content-index:before {
	content: '目次';
	display: block;
	font-size: 24.5px;
	margin-bottom: 15px;
}

他のスタイルとのバッティング回避した部分を除くとこれだけ。シンプルに線を引くことと色味の調整くらい。

SEO的な観点とか

目次足すと SEO に効果あるのかわからんけど、ふつうに見ていて、長めの投稿だったら合ったほうが便利だよね、とは感じる。

一応 Fetch as Google をして Google Bot にこの目次が認識されていることは確認したので、まあいいんじゃないかな。

この記事はどうでしたか

前後の記事

Next:
Prev: