カテゴリー
WordPressカスタマイズ

WordPressでページ内目次を見出しタグから自動生成(プラグインなし)

Wikiをはじめ、記事の先頭にリストの目次(インデックス)をつけているサイトを目にしたことがあると思います。
記事の内容がざっと理解でき、さらにクリックすることでスクロール移動できます。
訪問者にはとても優しい構成ですね。
ただし、このリストの目次は手作業で行うとかなり面倒です。
ユーザービリティの向上につながるとはいえ、投稿時に手間が掛かってはいただけません。

このサイトでも実装していますが、WordPressの場合は「Table of Contents Plus」などのプラグインで機能追加することができます。
今回はjQueryを使って、自前で実装してみたいと思います。

jQueryの確認

前提としてjQueryがロードされている必要があります。ソースのヘッダ内で下記のようにjQuery.jsが出力されているか確認してください。

<script type='text/javascript' src='http://example.com/wp-includes/js/jQuery/jQuery.js'></script>

WordPressではあらかじめjQueryのライブラリが用意されていますが、お使いのテーマでロードされていないようでしたら、ヘッダ内にjQueryを読み込む関数を入れてください。
場所は他のスクリプト類よりも先に読み込むようwp_head()のすぐ上でよいと思います。

<?php wp_enqueue_script('jQuery'); ?>
<?php wp_head(); ?>
</head>

スクリプトの追加

jQueryの確認ができたら、hタグを抽出してページ内リンクを自動生成させるスクリプトを加えます。

メインスクリプト

ソース6行目でどの見出しを目次として取得するかを指定しています。下記のソースではarticleタグ内のh3h4と定義していますので、必要に応じて変更ください。
例えば、ただのh3という形で指定するとページ内のサイドバーやメニューなど、すべての見出しタグが対象となりますので、ご注意ください。

<script>
jQuery(function($) { // h3~h4タグから目次を自動生成
  var idcount = 1;
  var toc = '';
  var currentlevel = 0;
  $("article h3,article h4:header", this).each(function() {
    this.id = "chapter-" + idcount;
    idcount++;
    var level = 0;
    if (this.nodeName.toLowerCase() == "h3") {
      level = 1;
    } else if (this.nodeName.toLowerCase() == "h4") {
      level = 2;
    }
    while (currentlevel < level) {
      toc += '<ol class="chapter">';
      currentlevel++;
    }
    while (currentlevel > level) {
      toc += "<\/ol>";
      currentlevel--;
    }
    toc += '<li><a href="#' + this.id + '">' + $(this).html() +
      "<\/a><\/li>\n";
  });
  while (currentlevel > 0) {
    toc += "<\/ol>";
    currentlevel--;
  }
  jQuery("#toc").html(toc);
});
</script>

スムーススクロール用スクリプト

上記のスクリプトで目次自体は出力されますが、せっかくなのでリンク先までスムーススクロールさせてみます。

<script>
jQuery(document).ready(function($) {
  $('a[href^="#"]').click(function(event) { // #で始まるアンカー
    var id = $(this).attr("href"); // 移動先を取得
    var offset = 60;
    var target = $(id).offset().top - offset;
    jQuery('html, body').animate({
      scrollTop: target
    }, 400); // スクロールの速度
    event.preventDefault();
    return false;
  });
});
</script>

これでリンク先まで視覚的に移動させることができます。

外部ファイルとして読み込む

外部JSファイルとして読み込む場合はjavascriptタグの中身を別ファイルとして保存して以下のようにヘッダ内に読み込みます。(ルートのjsフォルダにauto-link.jsとしてアップロード)

<script type="text/javascript" src="http://example.com/js/auto-link.js"></script>

目次のデザインに関してはスタイルシートでカスタマイズすることができます。
参考までにこのサイトで使っている目次部分のCSSは下記です。

<code>#toc {
  padding: 5px 0 25px;
}
ol.chapter {
  display: block;
  font-size: 14px;
  padding: 3px 20px;
}
ol.chapter li {
  list-style: circle;
}

自動生成見出しの使い方

通常どおり記事を書いていって構いません。目次にしたい部分にh3h4タグを使用します。
そして、目次を表示したい部分に以下のタグを挿入します。記事投稿時にはこれだけの手順で見出しに対する目次が指定カ所に出力されます。

<div id="toc"></div>

なお、この以前紹介したAddQuicktagを使用するとワンクリックでタグ挿入することができます。

見出しにhタグを使い、指定タグを挿入するだけ
見出しにhタグを使い、指定タグを挿入するだけ

動かない場合はここをチェック!

6行目("article h3,article h4:header",this)内のメインスクリプトの対象範囲はご自身のソースによって変更する必要があります。

例えば、WordPressで人気のデフォルトテーマ「Twenty Fourteen」であれば、メインコンテンツの記事部分はentry-contentというクラス内にありますので、ここのh3h4からを目次を作りたければ、(".entry-content h3,.entry-content h4:header",this)となります。

ちなみにjQueryのライブラリさえ使えれば、静的HTMLでもこの見出しメニュースクリプトは使えます。

profile image

執筆:R3098

WEBサービス構築・監修が生業です。WordPress 関連では Aurora Heatmap などのプラグイン開発も行っています。サイト運営者の力になりたいと考えます。

「WordPressでページ内目次を見出しタグから自動生成(プラグインなし)」への5件の返信

初めまして。

通常のHTMLサイトに設置したくて、
直前にCDN版jQueryを追加して、
メイン&スムースのコードを外部JSにして、
記述しても表示されないのですが、
こちらの記事内のコードは当たっているのでしょうか?
メイン&スムースのコードを外部JSも直前に入れるのでしょうか?

がちょぴんさん

メインスクリプトの下記6行目の変数括弧内は実際のHTMLでの対象を指定されていますか?
(“article h3,article h4:header”,this)
サンプルの場合はarticle h3とarticle h4というIDに対して見出しリストを作成します。
つまり(“h3:header”,this)とした場合はサイドバーなども含めたページ内すべてのh3見出しがメニューとなります。
一度、これで試してみて動かないようでしたら、それ以前の部分に問題がありますね。

ご返信ありがとうございます。

h3:header thisで表示されたのですが、
記事内だけで目次を表示させる場合は、
どのように記述すればいいのでしょうか?
記事のメイン?となるクラスをh3部分に変えても表示されないので、
コードのどこを変更したらいいのか分からず大変困っております。

また、目次をクリックする実際に、
URLに#付けたくなのですが、コードの何行名を削除すればいいのでしょうか?

自己解決しましたので大丈夫です。
h3:header this等の部分をご利用サイトに合わせて変更する所、大変勉強になりました。

動作したようでよかったです。

>h3:header this等の部分をご利用サイトに合わせて変更

ちょっと分かりづらかったでしょうか。
そのうち、追記しておきますね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトは reCAPTCHA によって保護されており、Google のプライバシーポリシー および 利用規約 に適用されます。

reCaptcha の認証期間が終了しました。ページを再読み込みしてください。