jquery 投稿日:2017/08/31

ページ内の見出しを拾い自動で目次を作るjs関数


ページ内目次をもっと簡単に設置したい。hタグからテキストを拾って自動で目次リストを作ってくれるjavascript(jQuery)を書いてみました。静的HTMLでもCMSでも簡単にお使いいただけます。




動作イメージ
動作イメージ

コンテンツの目次を付けたいけど、目次を作るために既存コンテンツから見出しをコピペしたり全ページに適用したりという作業が面倒だったので作りました。

言語はjavascript(jQuery)です。

動作イメージ

指定したセレクタ内の見出し(h2とかh3とか)を収集し、リストタグとアンカーに変換して、任意の箇所に目次としてappendします。

appendされた目次をクリックするとその見出しまでスクロールします。

自動目次を出すページと出さないページを簡単に制御可能にします。

完成したコード

var appendTOC = !function() {
    // 設定
    var correctTarget = '#content';
    var correctTargetHeadings = 'h2, h3';

    //#toc要素が存在する場合のみ動作
    if ($('#toc').length <= 0) return false;

    //見出しを収集
    var $h = $(correctTarget).find(correctTargetHeadings);

    // 目次を作成
    var html = '<ul class="toc-list">';
    $h.each(function(i, v) {
    	var c = 'toc-' + $(v).context.nodeName.toLowerCase();
        html += '<li class="' + c + '"><a data-toc="' + i + '">';
        html += $(v).text();
        html += '</a></li>';
    });
    html += '</ul>';

    $('#toc').html(html);

    //目次クリック時のスクロールイベント
    $(document).on('click', '#toc .toc-list a', function() {
        var no = +$(this).attr('data-toc');
        var target = $(correctTarget).find(correctTargetHeadings)[no];
        var targetPosition = $(target).offset().top;
        $('body,html').animate({
            scrollTop: targetPosition
        }, 500, 'swing');
        return false;
    });
}();

appendされるHTMLのサンプル

<ul class="toc-list">
    <li class="toc-h2"><a data-toc="0">h2</a></li>
    <li class="toc-h3"><a data-toc="1">h3</a></li>
    <li class="toc-h2"><a data-toc="2">h2</a></li>
    <li class="toc-h3"><a data-toc="3">h3</a></li>
    <li class="toc-h2"><a data-toc="4">h2</a></li>
    <li class="toc-h3"><a data-toc="5">h3</a></li>
</ul>

olの入れ子にするのが正当ですが実用性に何も問題はないでしょう。

使い方

jsの読み込みと設定

上記のjavascriptをどこかで読み込んでください。

見出しを収集する範囲はcorrectTargetの値で任意に指定してください。

収集する見出しのセレクタはcorrectTargetHeadingsで指定してください。

目次タグの配置

サイト内の任意の箇所に<div id="toc"></div>を設置してください。

自動で目次リストが現れます。

一応目次のスタイルのサンプル

目次が画面幅いっぱいに横並びで均等に配置されます。 flex使ってますので注意。scssですので注意。

#toc .toc-list {
  margin: 0;
  padding: 0;
  text-align: center;
  display: flex;
  justify-content: space-around;
  background-color: #eee;
}
#toc .toc-list li {
  list-style-type: none;
  width: 100%;
}
#toc .toc-list li a {
  padding: 1em;
  display: block;
  position: relative;
  border-left: solid 1px #fff;
}
#toc .toc-list li a::after {
  content: "";
  border: 8px solid transparent;
  border-top: solid 10px #eee;
  height: 0px;
  width: 0px;
  position: absolute;
  top: 100%;
  left: 50%;
  transition-duration: 0.15;
}
#toc .toc-list li a:hover {
  background-color: blue;
  color: #fff;
}
#toc .toc-list li a:hover::after {
  border-top: solid 10px blue;
}

comments powered by Disqus