ページ内目次をもっと簡単に設置したい。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;
}