hタグでスムーススクロール付きページインデックスを自動で生成する

ヘッダ画像

ページ内目次を見出しタグから自動生成

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タグ内のh3とh4と定義していますので、必要に応じて変更ください。
例えば、ただのh3という形で指定するとページ内のサイドバーやメニューなど、すべてのh3タグが目次となってしまいますので、ご注意ください。

<script type="text/javascript">
jQuery(function(){// H3とH4タグから目次を自動生成
var idcount = 1;
var toc = '';
var currentlevel = 0;
jQuery("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 + '">' + jQuery(this).html() + "<\/a><\/li>\n";

});
while(currentlevel > 0) {
toc += "<\/ol>";
currentlevel–;
}
jQuery("#toc").html(toc);
});
</script>

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

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

<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('a[href^="#"]').click(function(event) {// #で始まるアンカー
var id = jQuery(this).attr("href");// 移動先を取得
var offset = 60;
var target = jQuery(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は下記です。

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

自動生成見出しの使い方

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

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

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

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

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

WordPress以外で使う場合には?

実はjqueryをWordPressで使う場合はちょっとした決まりごとがあります。
WordPressでは標準でjqueryのライブラリを読み込んでいますが、このライブラリではjqueryで関数としてよく使用される「$」を使えません。
回避方法はいくつかあるのですが、上記のソースでは変数定義の「$」を「jQuery」に書き換えてあります。WordPress以外で使用する場合は下記をご使用ください。

メインスクリプト(静的なhtmlサイト用)

<script type="text/javascript">
$(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–;
}
$("#toc").html(toc);
});
</script>

スムーススクロール用スクリプト(通常のhtmlサイト用)

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

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

ちょっと分かりづらかったようですので、メインスクリプトの対象範囲について補足しておきます。
6行目(“article h3,article h4:header”,this)内はご自身のソースによって変更する必要があります。

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

コメント一覧

  1. がちょぴん より:

    初めまして。

    通常の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等の部分をご利用サイトに合わせて変更

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

コメントを残す

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

関連記事

「トップに戻る」ボタンでスマホでのユーザビリティアップ!

ウェブサイト上でコンテンツを下にスクロールさせると「トップに戻る」ボタンが出現して、クリックするとビ […]

WordPressで現在のページ表示に使用しているテンプレートをすべて知る

WordPressでは、投稿タイプに応じてデフォルトの構成テンプレートが適用されます。 ただし、プラ […]

メールフォームプロCGIをWordPressに設置

WordPressのフォームについて、定番のContact Form7をはじめ、いろいろとプラグイン […]

noindexを任意のページに出力する

SEOでは欠かせないmetaタグのnoindex WordPressでは通常の静的HTMLサイトと違 […]