Hugoに開閉式の目次を実装する方法

  HUGO  




今まで記事の中に目次がなかったんですが、内容が長くなるとやっぱりあったほうが便利ですよね。前から欲しいなーと思っていたので調べてみました。

今回はこのブログで使っているHugo Themesというテーマを元に説明しています。使っているテーマごとにファイルが違うので適宜読み替えてください。

なお、目次の実装方法やCSSなどは他のサイトを参考にさせていただきました。記事の最後に「参考にさせていただいたサイト様」としてまとめてあります。

それではHugoに開閉式の目次を追加する方法をまとめてみます。

サンプルはこれです。

htmlファイルの修正

ブログ記事表示用のsingle.htmlを修正、目次表示用のtoc.htmlを作成します。

single.htmlの修正

/layouts/_default/single.htmlを以下のように修正します。

/*省略*/
{{ if eq .Params.toc true }}
  {{ partial "toc.html" . }}
{{ end }}
{{ .Content }} 
/*省略*/

{{ .Content }}の上に追加してください。

.Params.toctrueの時にtoc.htmlを呼び出します。

.Params.tocは後述のdefault.mdに追加します。

toc.htmlの新規作成

/layouts/partials/toc.htmlを新しく作成します。

<section class="js-toc">
    <div class="hidden_box">
        <input type="checkbox" id="label1" />
        <label for="label1"></label>
        <div class="hidden_show">
          {{ .TableOfContents }}
        </div>
    </div>
</section>

{{ .TableOfContents }}の箇所に目次が追加されます。

追加される目次は、本文で使っているHタグになります。

tocはTable of Contents(目次)の略です。

CSSファイルの修正

/static/css/style.cssに以下を追加します。cssファイルがなければ作成してください。

.hidden_box {
    margin: 2em 0;
    padding: 0;
    }
.hidden_show{
    background: #f8f8f8;
    border-radius: 5px;
    padding-left: -1em;
}
.hidden_box label {
    padding: 1em 0.8em;
    font-weight: bold;
    background: #9EC2F2;
    border-radius: 5px;
    cursor :pointer;
    transition: .5s;
}
.hidden_box label:before {
    display: inline-block;
    content: '\f078 目次を表示';
    font-family: 'FontAwesome';
    padding-right: 5px;
    transition: 0.2s;
}
.hidden_box label:hover {
    background: #84ACE7;
}
.hidden_box input:checked ~ label:before {
     content: '\f077 目次を非表示';
}
.hidden_box input {
    display: none;
}
.hidden_box .hidden_show {
    height: 0;
    padding: 0;
    overflow: hidden;
    opacity: 0;
    transition: 0.8s;
}
.hidden_box input:checked ~ .hidden_show {
    padding: 1em 0;
    height: auto;
    opacity: 1;
}

marginやpaddingの値はサイトに合わせて調整してください。

【12/4追記】
CSSの疑似要素に全角文字を使うと文字化けすることがあるようです。
日本語を表示する場合は、unicodeで記述してください。

目次[表示]  → \76EE\6B21\FF3B\8868\793A\FF3D
目次[非表示] → \76EE\6B21\FF3B\975E\8868\793A\FF3D
【追記ここまで】

javascriptの修正

/static/js/script.jsに以下を追加します。jsファイルがなければ作成してください。

var $tocPlace = $('#js-toc-place');
if ($tocPlace.length === 1) {
  $('.js-toc').appendTo($tocPlace);
}

default.mdの修正

目次の表示・非表示を制御するパラメーターをFront Matter1に追加します。

toc: true

目次を表示したくない場合は、toc: false、または、この行を削除します。

問題点

ここまでの修正で目次を表示してみると……

本文中に使っているタグの関係で余計な点が表示されてしまう。そこでcssで見た目の調整を行う。

このように余計な点が表示されてしまいます。

これは本文の中に<H1>タグを使っていないために起こることで、<h1>タグから順番に使っている場合は問題ありません。

ただ、記事を書く上で<H1>タグを使うことはまずないと思いますので、余計な点は消してしまいましょう。

見た目の調整

/static/css/style.cssに以下の内容を追加してください。

.hidden_box ul {
    list-style-type: none;
    padding-left: 1.5em;
} 
.hidden_box ul ul {
    list-style-type: disc;
}

不要な点を削除し、その分表示位置を左に詰めています。

余計な点が削除され表示位置も自然な位置に移動されているのが確認できます。

綺麗に表示されました。

(おまけ)シンプルな目次

表示・非表示を切り替えず常に表示する場合は、以下のものをお試しください。

<section class="js-toc">
  <div class="toc">
  {{ .TableOfContents }}
  </div>
</section>
.toc ul {
    list-style-type:none;
} 
.toc ul ul {
    list-style-type:disc;
}
.toc:before {
    content: "目次";
    font-size: 120%;
    font-weight: bold;
    padding-left: 3em;
}
.toc  {
    background: #f8f8f8;
    border-radius: 5px;
    padding: 1em;
}

クリックしないと表示されないのは面倒だったり非表示にする意味がわからないという場合は常に表示してしまいましょう。

【12/4追記】
全角文字はunicodeで記載してください。
目次 → \76EE\6B21
【追記ここまで】

参考にさせていただいたサイト様

あとがき

私の知識では到底実装できそうにないことだったので、記事を公開されているサイト様に感謝です!

実はシンプルな表示を実装した時点で諦めかけたんですが、なんとか実装できてよかったです。開きっぱなしだと邪魔になることがありますからね。

htmlやcssはイマイチ理解していないのでスマートではないかもしれませんが、動けばいいの精神でやってます。嘘です。日々勉強中です。

この他にも、マウスホバーで開いたり、もう少し見た目にこだわってみるのも面白そうですね。


  1. default.md内の---+++で囲まれた部分 [return]