Hugoで目次(Table of Contents, TOC)を安全&柔軟に表示・制御する方法まとめ

目次
概要
Hugoで.TableOfContents
を使えば、自動で記事の見出しから目次(TOC)を生成できる。ただし、目次のカスタム、空時の隠し方、多言語タイトル対応、デザイン調整など、つまづきやすいポイントも多い。このポストでは、TOC表示の基本と応用、よくある落とし穴、ベストプラクティスを一通りまとめる。
1. 目次の基本表示
以下をテンプレートに書くだけで、h2~h4見出しから自動で目次を生成する。
{{ .TableOfContents }}
この方法は手軽だが、デザインやタイトル調整には弱い。
2. ボックス化・タイトル追加
好みのデザインで中央寄せや枠線、背景色を加えたい場合:
<div class="toc-wrapper" style="text-align:center;"> <div class="toc-inner" style="display:inline-block; background:#f8f8f8; border:1px solid #ccc; border-radius:10px; padding:1em 2em;"> <h2> Table of Contents </h2> <nav id="TableOfContents" style="text-align:left;"> {{ .TableOfContents }} </nav> </div> </div>
3. 多言語でタイトルを切り替える(i18n不要)
i18nファイルや多言語ショートコードを使わなくても、シンプルな条件分岐だけで対応可能。
<h2>
{{ if eq $.Site.Language.Lang "ja" }}
目次
{{ else }}
Table of Contents
{{ end }}
</h2>
.Site.Language.Langが"ja"なら日本語、それ以外は英語タイトル。
4. 「見出しゼロ」時は目次ブロックごと非表示に
本来の落とし穴。h2などが無い記事でも.TableOfContentsは空HTMLや空文字列を返す場合が多い。ifやwithでは消せず、タイトルやボックスだけ空で残ることも。
一番堅牢な解決法:plainify & lenで内容チェック。
{{ $toc := .TableOfContents }}
{{ if gt (len (plainify $toc)) 0 }}
<div class="toc-wrapper toc-box" style="text-align:center; margin:2em auto;">
<div class="toc-inner" style="display:inline-block; background:#f8f8f8; border:1px solid #ccc; border-radius:10px; padding:1em 2em;">
<h2>
{{ if eq $.Site.Language.Lang "ja" }}目次{{ else }}Table of Contents{{ end }}
</h2>
<nav id="TableOfContents" style="text-align:left;">
{{ $toc | safeHTML }}
</nav>
</div>
</div>
{{ end }}
- plainifyでHTMLタグを除去しテキスト部分だけ残す
- lenで中身が1文字以上か判定、あればブロック全体を出力
5. テンプレートエラー対策(スコープ問題)
エラー例:
can't evaluate field Site in type template.HTML
この場合、with .TableOfContentsの中だと「.」がTableOfContents(HTML型)になるため.Site.Language.Lang参照不可。 グローバルスコープは$.Site.Language.Langでアクセス。
または先に$page := .で変数化しておき、
{{ if eq $page.Site.Language.Lang "ja" }}タイトル{{ else }}Title{{ end }}
のように使うのもOK。
6. TOCボックス用CSS例
.toc-wrapper {
text-align: center;
margin: 2em auto;
}
.toc-box .toc-inner {
display: inline-block;
background: #f8f8f8;
border: 1px solid #ccc;
border-radius: 10px;
padding: 1em 2em;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
#TableOfContents {
text-align: left;
}
まとめ
- .TableOfContentsで目次自動生成
- ラッピングデザインやタイトルはテンプレートで柔軟に調整可能
- 多言語条件分岐でタイトルも切り替えられる
- plainify+len判定で「見出しゼロ時は目次ごと非表示」を堅牢に実現
- withブロックやスコープには$や$page変数でアクセス
TOC回りのトラブル・工夫はこのベストプラクティス集を基準に組んでいくと安心。
著者について

Genx
1982年生まれ、日本人のビートメイカー・音楽プロデューサー。実験的なヒップホップビートを制作。国際的な環境で育ったため英語が話せる。趣味は筋トレ、アートワーク制作、ウェブサイトカスタマイズ、Web3。韓国が大好き。
ウェブサイト:genxrecords.xyz