WordPressでの目次表示。
普通はTOC+プラグインを使うと思います。
※ TOC = Table of Content
でも自分で目次表示したい人もいます。
- 極力プラグインを使いたくない
- 目次程度なら自力で表示したい
そういう変わった人のために、
プラグインなしで目次表示の方法を解説します。
目次
ここで行う目次実装の概要と注意点
大まかな手順はこのようになってます。
- 記事内の各見出しに自動でidを割り振る
- その見出し+idを元に目次を自動生成
- 目次内から見出しにスクロールもできる
こういう実装を目指すことにします。
当たり前だけど初心者向けではありません。
ギリギリ中級者向けかなという程度の内容です。
だから次の人は試さないでください。
- WordPressの仕組みを理解してない
- PHPコードを読めない書けない
そういう人がこの記事に手を出すと、
間違いなくトラブルの原因になります。
もし目次表示のカスタマイズが必要なら…
▼ こういうサービスもあるのでご相談を
警告しておきました(念押し)
1.使用中テーマのfunctions.phpを開こう
ここでは使用中テーマを編集していきます。
具体的にはfunctions.phpに対する編集作業です。
▼ 外観 ⇒ テーマファイルエディタを開く
▼ テーマファイル ⇒ functions.php を開く
これは本当に重要なファイルです。
この内容を編集して構文エラーが起きたなら、最悪ブログがダウンします。もっとも最近のワードプレスなら更新前に警告してくれますが…
だからここからは慎重に作業してください。
ここまでで2回も念押ししました。
2.見出しに自動でidを振るコード追加
見出しとはh2~h6タグまでのこと
その見出しに自動生成したidを割り当てます。
具体的にはfunctions.phpに以下を追加します。
▼ このようなPHPコード追加
function auto_id_to_headings( $content ) {
$content = preg_replace_callback(
'/(\<h[1-6](.*?))\>(.*)(<\/h[1-6]>)/i', function( $matches ) {
if ( ! stripos( $matches[0], 'id=' ) ) {
/// 見出しにidがないなら自動生成
$matches[0] = $matches[1] . $matches[2]
. ' id="' . sanitize_title( $matches[3] )
. '">' . $matches[3] . $matches[4];
}
return $matches[0];
}, $content );
return $content;
}
add_filter( 'the_content', 'auto_id_to_headings', 10 );
ポイントは見出しのタイトルから自動的にidを設定していることです。連番とか使う方法もあるけど、ここではこの方法を採用しました。
具体的には sanitize_title() によりタイトルから無効文字を除外し、idに使っても問題ない形式にしてます(参考記事 : https://elearn.jp/wpman/function/sanitize_title.html)
例えばこういう感じになるはず
<h2>Hello, I'm h2 tag</h2>
↓ 変換後 ↓
<h2 id="hello-im-h2-tag">Hello, I'm h2 tag</h2>
<h2>こんにちは、見出しです</h2>
↓ 変換後 ↓
<h2 id="%e3%81%93%e3%82%93%e3%81%ab%e3%81%a1%e3%81%af%e3%80%81%e8%a6%8b%e5%87%ba%e3%81%97%e3%81%a7%e3%81%99">こんにちは、見出しです</h2>
※ 日本語はエンコードされる
自動でタイトルからidが割り振られます。
3.目次(TOC)を自動生成・表示するコード追加
いよいよ目次(TOC)を生成・表示してみます。
ここでは最初の見出し前に表示してみました。
▼ その具体的なPHPコード
function collate_toc_row($depth, $anchor, $heading) {
$level = substr($depth, 1);
if ( $anchor ) {
return ["<a href='#{$anchor}' class='{$depth} toc-link'>{$heading}</a>", $level];
} else {
$slug = sanitize_title($heading);
return ["<a href='#{$slug}' class='{$depth} toc-link'>{$heading}</a>", $level];
}
}
function add_toc_before_1st_heading( $content ){
/// 目次を自動生成して最初の見出し前に表示
preg_match_all('/<(h\d*)(?: id="(.*?)")?>((.*?))</',$content,$matches);
$levels = $matches[1];
$anchors = $matches[2];
$headings = $matches[3];
if ( $headings ) {
/// 見出しが1つ以上あるなら目次表示
$toc = '<div class="toc_container">';
$toc .= '<div class="title">Table of Contents</div>';
$collated = array_map('collate_toc_row', $levels, $anchors, $headings );
$previous_level = 2;
$toc .= '<ol class="toc-list">';
foreach ($collated as $row) {
$current_level = $row[1];
if ( $current_level == $previous_level ) {
$toc .= '<li>' . $row[0];
} else if ( $current_level < $previous_level ) {
$toc .= str_repeat('</ol>', $previous_level - $current_level) . '<li>'. $row[0];
} else {
$toc .= '<ol><li>' . $row[0];
}
$previous_level = $row[1];
}
$toc .= str_repeat('</ol>', $previous_level) . '</li></ol>';
$toc .= '</div>';
$content_parts = preg_split("/(<h\d*)/", $content, 2, PREG_SPLIT_DELIM_CAPTURE);
$content = $content_parts[0] . $toc . $content_parts[1].$content_parts[2];
}
return $content;
}
add_filter( 'the_content', 'add_toc_before_1st_heading', 11);
長すぎるから細かな解説はしません。
記事内のすべての見出し(h1~h6)をスキャンし、それを元に目次を自動生成。最初の見出しの前にTOCを挟み込んでるだけです。
見出しが1つもない記事には目次表示されません。
4.目次のレイアウト用にCSSを追加
できあがった目次は質素な見た目です。
だからレイアウトを整えます。
具体的には次のようなCSSコードを追加しました。
▼ 目次に適用したCSSコード例
.toc_container{
overflow: auto;
padding: 10px;
background: #f9f9f9;
border: 1px solid #aaa;
}
.toc_container .title{
text-align: center;
padding-top: 10px;
}
.toc-list{
list-style: none;
font-size: 20px !important;
margin: 0;
padding: 10px;
float: left;
position: relative;
left: 50%;
transform: translateX(-50%);
}
.toc-list ol{
list-style: none;
}
.toc-list a{
font-size: 16px;
}
ここまで読み進められる人なら「このCSSどこに追加すればいいの?分からないよ~(泣」なんてバカなことは言わないはずです。
好きなようにCSSは改変してください。
こんなビジュアルの目次ができた!
できあがった目次はこんなビジュアルです。
見てわかる通り、レイアウトは完全にTOC+プラグインのそれです。あと目次リンクをクリックすると各見出しにスクロールもしてくれます。
まだ未完全だけど目次としては機能してます。
WordPressでプラグインなしでの目次の作り方は以上。
チャレンジ精神のある人は試してみてください。
フク郎
最新記事 by フク郎 (全て見る)
- 最大5,000円報酬をもらうために、招待を受入れていただけませんか? - 8月 27, 2024