「HTMLで目次を作りたいけれど、どのタグを使えばよいのか分からない」「目次のデザイン例も見てみたい」と困っていませんか?
HTMLの目次は、番号付きリストとページ内リンクを組み合わせて作ります。基本を覚えれば、ブログ記事や長い解説ページでも目的の見出しへすぐ移動できるようになります。
この記事では、「HTMLで目次を作る方法」「階層を深くする方法」「目次のデザイン3例」の順に解説します。実際の表示結果を確認しながら進めていきましょう。
HTMLで目次を作る方法

基本的な目次の作り方
目次の項目には、番号付きリストを作るolタグ、項目を表すliタグ、リンクを作るaタグを使います。目次全体は「ページ内の案内」であることが伝わるように、navタグで囲みます。
リンクをクリックして見出しへ移動するには、aタグのhref="#id名"と、移動先の見出しに付けるid="id名"を一致させます。
移動先のidとhrefを一致させることで、aタグで作った目次をクリックすると対応する見出しへ移動できます。
olタグとliタグの基本は、次の記事で詳しく解説しています。
まずは、次のHTMLをindex.htmlへ書いてみてください。
<nav class="table-of-contents" aria-label="目次">
<ol>
<li><a href="#chapter1">目次1</a></li>
<li><a href="#chapter2">目次2</a></li>
<li><a href="#chapter3">目次3</a></li>
<li><a href="#chapter4">目次4</a></li>
<li><a href="#chapter5">目次5</a></li>
</ol>
</nav>
<h2 id="chapter1">目次1の内容</h2>
<p>ここに本文を書きます。</p>
<h2 id="chapter2">目次2の内容</h2>
<p>ここに本文を書きます。</p>
<h2 id="chapter3">目次3の内容</h2>
<p>ここに本文を書きます。</p>
<h2 id="chapter4">目次4の内容</h2>
<p>ここに本文を書きます。</p>
<h2 id="chapter5">目次5の内容</h2>
<p>ここに本文を書きます。</p>目次部分は次のように表示されます。

目次1をクリックすると、id="chapter1"を付けた見出しまでページ内を移動します。ほかの項目も、hrefとidが対応していれば同じように動きます。
リンクの色はcolorプロパティで変更できます。text-decoration: none;で下線を消すこともできますが、その場合も色やフォーカス表示を残し、リンクだと分かるデザインにしてください。
固定ヘッダーで見出しが隠れる場合
ページ上部に固定ヘッダーがあると、目次をクリックしたときに移動先の見出しがヘッダーの下へ隠れることがあります。

この場合は、移動先の見出しへscroll-margin-topを指定します。ページ内リンクで移動したとき、見出しの上に指定した分の余白が確保されます。
h2[id],
h3[id] {
scroll-margin-top: 80px;
}上の例では、idを付けたh2・h3見出しの上に80pxの余白を確保しています。80pxの部分は、実際に使っている固定ヘッダーの高さに合わせて調整してください。
目次の階層を深くする方法
次に、目次を「2.1」「2.1.1」のような階層にする方法を説明します。h2の中にh3、h3の中にh4があるページなど、見出し同士の親子関係を表したいときに使います。
子階層のolタグは、親になるliタグの中へ入れます。見た目のためだけに階層を増やさず、本文の見出し構造とそろえることが大切です。
<nav class="toc-hierarchy" aria-label="目次">
<ol>
<li><a href="#chapter1">目次1</a></li>
<li>
<a href="#chapter2">目次2</a>
<ol>
<li>
<a href="#chapter2-1">目次2.1</a>
<ol>
<li><a href="#chapter2-1-1">目次2.1.1</a></li>
<li><a href="#chapter2-1-2">目次2.1.2</a></li>
</ol>
</li>
<li><a href="#chapter2-2">目次2.2</a></li>
</ol>
</li>
<li><a href="#chapter3">目次3</a></li>
<li><a href="#chapter4">目次4</a></li>
<li><a href="#chapter5">目次5</a></li>
</ol>
</nav>階層の番号はCSSカウンターで自動表示できます。目次以外のリストへ影響しないように、ここでは.toc-hierarchyの中だけを指定しています。
.toc-hierarchy ol {
counter-reset: item;
list-style: none;
padding-left: 1.5rem;
}
.toc-hierarchy li {
counter-increment: item;
margin-block: 0.4rem;
}
.toc-hierarchy li::before {
content: counters(item, ".") " ";
}表示結果は次のとおりです。

counter-resetは番号を数え始める準備、counter-incrementは項目ごとに番号を1つ進める指定です。counters()を使うことで、親と子の番号をピリオドでつないで表示できます。
目次のデザイン3選

ここからは、目次のデザインを3つ見ていきます。
- 目次をボックスで囲む
- 数字を01の形式にして下線を引く
- 数字を丸で囲む
3例とも同じol・li・aタグを使い、主にCSSで見た目を変えています。HTMLの意味を保ったままデザインできる点を確認してください。
目次をボックスで囲む
最初は、目次全体を枠と背景色で囲む基本的なデザインです。本文との境界が分かりやすく、項目が多い目次にも使いやすい形です。
<nav class="toc-box" aria-label="目次">
<ol>
<li><a href="#chapter1">目次1</a></li>
<li><a href="#chapter2">目次2</a></li>
<li><a href="#chapter3">目次3</a></li>
<li><a href="#chapter4">目次4</a></li>
<li><a href="#chapter5">目次5</a></li>
</ol>
</nav>.toc-box {
width: min(100%, 36rem);
padding: 1.25rem 1.5rem;
border: 1px solid #94a3b8;
border-radius: 0.5rem;
background-color: #eff6ff;
box-sizing: border-box;
}
.toc-box ol {
margin: 0;
padding-left: 1.5rem;
}
.toc-box li + li {
margin-top: 0.4rem;
}表示させると次のようになります。

元のコードにあった固定の高さは外し、項目が増えたり文字が折り返されたりしても枠が自然に広がるようにしています。width: min(100%, 36rem);により、スマートフォンでも画面幅からはみ出しません。
数字を01の形式にして下線を引く
次は、番号を「01」「02」の形式で表示し、番号の下へ線を引くデザインです。番号はHTMLへ一つずつ書かず、CSSカウンターで自動的に追加します。

<nav class="toc-zero" aria-label="目次">
<ol>
<li><a href="#chapter1">目次1</a></li>
<li><a href="#chapter2">目次2</a></li>
<li><a href="#chapter3">目次3</a></li>
</ol>
</nav>.toc-zero ol {
counter-reset: item;
list-style: none;
margin: 0;
padding: 0;
}
.toc-zero li {
counter-increment: item;
display: flex;
align-items: center;
gap: 1rem;
margin-top: 0.5rem;
}
.toc-zero li::before {
content: counter(item, decimal-leading-zero);
padding-bottom: 0.2rem;
border-bottom: 2px solid #2563eb;
font-size: 1.4rem;
}decimal-leading-zeroは、一桁の番号の先頭へ0を付ける指定です。項目を追加しても番号を手作業で直す必要がないため、更新時の間違いを減らせます。
数字を丸で囲む
最後は、目次の番号を丸で囲むデザインです。こちらもCSSカウンターを使い、HTMLは通常のリストのままにします。
<nav class="toc-circle" aria-label="目次">
<ol>
<li><a href="#chapter1">目次1</a></li>
<li><a href="#chapter2">目次2</a></li>
<li><a href="#chapter3">目次3</a></li>
</ol>
</nav>.toc-circle ol {
counter-reset: item;
list-style: none;
margin: 0;
padding: 0;
}
.toc-circle li {
counter-increment: item;
display: flex;
align-items: center;
gap: 0.75rem;
margin-top: 0.5rem;
}
.toc-circle li::before {
content: counter(item);
display: grid;
width: 2.25rem;
aspect-ratio: 1;
place-items: center;
flex: 0 0 auto;
border-radius: 50%;
background-color: yellow;
}表示結果は次のとおりです。

widthとaspect-ratio: 1;で縦横を同じ長さにし、border-radius: 50%;を指定すると円になります。display: grid;とplace-items: center;は、数字を円の中央へ配置するための指定です。
CSSを使わず、HTMLの文字参照で丸数字を表示する方法もあります。たとえば①は「①」、❶は「❶」、⓪は「⓪」と表示されます。

文字参照は手軽ですが、用意されている記号の範囲に限られます。色や大きさを自由に調整したい場合や、項目数が増える場合はCSSカウンターを使う方法が向いています。
丸数字の種類や入力方法は、次の記事でも紹介しています。
まとめ
HTMLの目次は、ol・li・aタグで項目を作り、リンクのhref="#id名"と見出しのid="id名"を対応させます。階層を増やす場合は、本文の見出し構造に合わせてolタグを入れ子にしてください。
基本の目次が動いたら、ボックス、01形式の番号、丸数字の順にCSSを試してみましょう。最後にすべてのリンクをクリックし、目的の見出しへ移動するか、スマートフォンで横にはみ出さないかを確認すれば完成です。
