[Blogger] 目次を自動生成する方法(カスタマイズ方法とスクロールアニメーション付き)

Blogger

blogger table of contents

目次は、読者が読みたい部分にジャンプしたり記事のあらすじをつかんだりするのに役立つため、多くのブログで目にします。記事が長くなるほど見やすくなって良いですよね。でも、毎回手で目次を作るのは時間がかかります…。

この記事では、Bloggerで目次を自動生成する方法をご紹介します。コピペでOKです。目次のカスタマイズ方法と、各見出しを押した時のスクロールアニメーション(瞬間移動ではなく、スルスルっと移動するやつ)の追加方法も合わせてお伝えします。

最初は「スケ郎」さん作のプラグイン([Blogger] 目次を簡単に自動生成(忙しい人向けのコピペ素材)-スケ郎のお話)を入れていたのですが、そのJavascriptコードが理解できず…自分なりに勉強した結果、全然違うコードができました。あれほど高機能ではありませんが、シンプルでコードは見やすいかなと思います。後半で、自由にカスタマイズできるようにコードの解説もしたいと思います。

kamokamoTOC の特徴

便宜上、"kamokamoTOC"と呼ぶことにします。"TOC"は"Table Of Contents"の略です。kamokamoTOCの特徴は、以下の通りです。

動作

  1. 記事中のh2,h3,h4タグを自動検出して順番にid属性を付ける
  2. 最初のh2タグの上に目次を自動で設置(h2タグがなければ表示しない)
  3. 目次の見出しをクリックするとその位置に移動

自動目次の動作はスケ郎さんのと同じ(はず)です。

ちなみに、h2,h3,h4と階層を順次下っていく前提なので、h2の次にh4を置くと表示がおかしくなります。その点はご注意ください。h4からh2に戻るのは問題ないです。

長所

  1. jQueryを使用し、コードの可読性とカスタマイズ性を重視
  2. Google検索結果に見出し(ジャンプリンク、サイトリンク)が表示される可能性を高める

長所は可読性とカスタマイズ性に尽きます。

Google検索結果のジャンプリンクやサイトリンク表示はGoogleの判断であり、自分ではコントロールできないので、この目次を入れれば必ず出るというものではありませんが、各見出しにリンクを作ることでその可能性を高めます。これは他の自動目次も同じだと思いますが。

短所

  1. jQueryを使用している分、ページの読み込みが少し遅いかも
  2. 設置する場所は「最初のh2タグの上」固定
  3. 表示・非表示は選べない(必ず表示)

コードが見やすい分、機能を絞ったので、自由度は低いです。知識のある方ならカスタマイズで何とでもなるとは思います(改善したら教えてください)。

jQueryは純粋なJavascriptよりも遅いと言われていますが、体感としては変わらないので、この程度ならあまり影響はないのだと希望的観測をしています。

コピペ用コード

以下のコードを、HTML編集画面で指定の場所にコピペすれば導入できます。kamokamoTOC本体とスクロールアニメーションを分けて書きます。

「HTML編集画面って何…?」という方は、まずこちらのページをご覧ください。戻せなくなった時のために、HTMLのバックアップは必ず取ってくださいね。

jQuery

jQueryを入れていない方は、まず以下のコードをHTML編集画面の</head>タグの上にコピペしてください。

    <!-- jQuery -->
    <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js'/>
  

kamokamoTOC本体

以下のコードを、上記jQueryの下(</head>タグの上)にコピペしてください。CSS(<style>タグ以下)は別の場所に置いてもかまいません。

    <!-- [START] TOC Top -->
    <b:if cond='data:view.isSingleItem'>
      <script defer>
      //<![CDATA[
      $(function(){
        var toc="<ol class='h2list'>";
        var h2cnt=0;
        var h3cnt=0;
        var h4cnt=0;
        $(".post-body h2,.post-body h3,.post-body h4", this).each(function() {
          var prefix='';
          var chapter='';
          var node=this.nodeName.toLowerCase();
          if (node == "h2") {
            if(h3cnt>0 && h4cnt==0){
              prefix = "</li></ol></li>";
			}else if(h4cnt>0){
     		  prefix = "</li></ol></li></ol></li>";
            }else{
              prefix = "</li>";
            }
            h2cnt++;
            h3cnt=0;
            h4cnt=0;
            chapter+=h2cnt;
          } else if (node == "h3") {
            if(h3cnt==0){
              prefix = "<ol class='h3list'>";
            }else if(h4cnt>0){
              prefix = "</li></ol></li>";
            }else{
              prefix = "</li>";
            }
            h3cnt++;
            h4cnt=0;
            chapter+=h2cnt+"-"+h3cnt;
          } else if (node == "h4") {
            if(h4cnt==0){
              prefix = "<ol class='h4list'>";
            }else{
              prefix = "</li>";
            }
            h4cnt++;
            chapter+=h2cnt+"-"+h3cnt+"-"+h4cnt;
          }
          var caption=$(this).text();
          //$(this).html("<span id='"+chapter+"'>"+caption+"</span>");
          $(this).attr('id',chapter);
          toc += prefix + "<li><a href='#" + chapter + "'><span>" + caption + "</span></a>";
        });
        toc+="</li></ol>"
        $(".post-body h2").first().before("<div id='toc'><div id='toc-header'><p>Table of Contents</p></div>"+toc+"</div>");    
      });
      //]]>
      </script>
      <style>
      #toc{
        background:#f1f8ff;
        border:dotted 2px #779cff;
        border-radius:5px;
        padding:10px;
        margin:1em auto .5em auto;
        width:auto;
        display:table;
      }
      #toc-header{
        text-align:center;
        font-size:120%;
        border-bottom:1px solid black;
        margin-bottom:.5em;
      }
      #toc a{
        color:#779cff;
        font-size:100%;
      }
      .h2list,.h3list,.h4list{
        border:none;
        margin:0;
	  }        
      .h2list{
        list-style-type:upper-roman;
      }
      .h3list{
        list-style-type:lower-roman;
      }
      .h4list{
        list-style-type:square;
      }
      </style>
    </b:if>
    <!-- [END] TOC Top -->
  

これでkamokamoTOC本体の導入は完了です。保存して、自分の記事を見て目次が作られていることを確認してください。

何もできていない場合、scriptの編集が必要だと思われます。また、テンプレートや他のカスタマイズとCSSが競合して表示がおかしくなる可能性もあります。詳しくは後述のコード説明をご覧ください。

スクロールアニメーション

kamokamoTOC本体だけでは、目次のリンクをクリックすると瞬間移動してしまい、どこまで移動したか分かりづらいです。そこで、スクロールアニメーションを入れて分かりやすさと楽しさを出しましょう。

以下のコードを、今度は</body>タグの上にコピペしてください。目次本体はページ読み込み時に表示させたいのでhead内に置きましたが、アニメーションは表示と関係ないので最後に置いた方がページ読み込みが多少速くなります。

    <!-- [START] TOC Scrolling Animation -->
    <script>
    $(function(){
      $('[href^="#"]').click(function(){
        var id= $(this).attr('href');
        var position=$(id).offset().top-50;
        $('html,body').animate({'scrollTop':position},800);
        //return false;
      });
    });
    </script>
    <!-- [END] TOC Scrolling Animation -->
  

これで導入は完了です!

コード説明とカスタマイズ方法

以下でコードとカスタマイズ方法の説明をします。長くなるので、まずカスタマイズに関わる部分を説明します。

kamokamoTOC本体

まず、scriptでカスタマイズに関わる部分です。上から10行目、そしてscript終了タグから3行上です。

$(".post-body h2,.post-body h3,.post-body h4", this).each(function() {
  
$(".post-body h2").first().before("<div id='toc'><div id='toc-header'><p>Table of Contents</p></div>"+toc+"</div>"); 
  

上は、記事本文("post-body"というclassで囲まれた部分)の各h2,h3,h4タグに対して処理を行う関数宣言です。もし目次が作られなかった場合、このclass名が違う可能性が高いです(QooQやBlogger公式テンプレートのNotableは同じでした)。class名を調べて、上3か所と、下1か所の計4か所を変更してください。class名の調べ方は、「HTML編集画面で探す」か「Google Chromeの検証ツールで見る」どちらかが良いと思います。分からなかったらコメントしてください。できる限り調べます。

下は、記事本文の最初のh2タグの上に目次を追加する部分です。ここで"Table of Contents"というのが目次のタイトルなので、好きに変えてください。


次に、CSSです。ここで見た目が決まります。説明代わりにコメントを付けてみました。

      <style>
      #toc{
        background:#f1f8ff; /*背景色*/
        border:dotted 2px #779cff;  /*枠線スタイル、太さ、色*/
        border-radius:5px;  /*枠線の角の丸み*/
        padding:10px; /*文字と枠線の間の余白*/
        margin:1em auto .5em auto;  /*枠線とその周囲の余白*/
        width:auto; /*幅を文字長さに合わせる*/
        display:table;  /*幅を文字長さに合わせて中央寄せ*/
      }
      #toc-header{  /*タイトル*/
        text-align:center;  /*中央寄せ*/
        font-size:120%; /*文字サイズ*/
        border-bottom:1px solid black;  /*下線*/
        margin-bottom:.5em; /*下線の下の余白*/
      }
      #toc a{ /*リンク部分*/
        color:#779cff;  /*文字色*/
        font-size:100%;
      }
      .h2list,.h3list,.h4list{
        border:none;
        margin:0;
	    }        
      .h2list{
        list-style-type:upper-roman;  /*大文字ローマ数字*/
      }
      .h3list{
        list-style-type:lower-roman;  /*小文字ローマ数字*/
      }
      .h4list{
        list-style-type:square; /*四角マーク*/
      }
      </style>
  

特に重要なのは「色」と「リストスタイル」だと思うので、補足します。

は、以下の色見本サイトが分かりやすいので、ここから好きな色を選んでください。

WEB色見本 原色大辞典 - HTMLカラーコード

リストスタイルは、こちらのサイトで一覧が見れます。使うかどうかは別として、かなりいろいろ選べます。

list-style-type - CSS: カスケーディングスタイルシート | MDN

その他のscriptコードは、量も多くて説明が長くなるので、気が向いたら順次追記していく形で…。

スクロールアニメーション

こちらは短いのでさらっと説明します。

var position=$(id).offset().top-50;
$('html,body').animate({'scrollTop':position},800);
//return false;
  

カスタマイズの余地があるのは、この3行です。

1行目は、スクロールを止める位置を決めています。数字を小さくするほど上で止まります。当ブログはヘッダを固定しているので、ヘッダと見出しが重ならないようにtop-50としています。

2行目は、アニメーションの内容と時間を決めています。この800という数字は「800ミリ秒で移動する」という意味で、数字を小さくするほど短時間で移動します。

3行目は、目次の各見出しリンクをクリックしたときにURLを変更するかどうかを決めています。コメントアウトしているこの状態では、URLが変更されて、例えば "https://itchingears-kamokamo.blogspot.com/2020/10/s1-ja-usability-and-itchy-points.html#2-1" のように "#" 以下が追加されます。コメントアウトを解除する("//"を消す)と、見出しをクリックしてもURLが変わりません。

これは好みだと思いますが、URLが変わるとスマホで見る時に「見出しをクリック」⇒「最初に戻りたいので戻るボタンをクリック」ということができたり、最初からその見出しの部分に飛ばすリンクを簡単に共有できたりといったメリットがあります(それがデメリットだと感じる人もいます)。

おわりに

Bloggerで目次を自動で追加する方法をご紹介しました。ぜひ使ってみてください。コードの説明は順次追記していきます。高速化・高機能化も検討したいと思っているので、できたら別記事を書きます。また、当ブログではサイドバーにも「ついてくる目次」を付けているので、それも別記事で紹介する予定です。

改造リストは随時更新してます!

About Me

My photo
かもとしゃけ。聖書と音楽。
Follow Me?

Labels

Blogger (14) Other (3) Studio One (1) Tool (6)

Table of Contents