ページ内のセクション構造を可視化し、読者が任意のセクションへ直接ジャンプできるナビゲーションUI。長文記事・ドキュメント・設定画面で「今どこにいるか」と「どこへ行けるか」を同時に伝える。
この記事を読むと、スクロール連動アクティブ追跡・スムーズスクロール・スキップリンクとの違い・スクリーンリーダー向けのaria-label設計が自分でできるようになります。
1. UI例(Preview / Live)
2. 定義(Definition)
ページ内の見出し(<h2>・<h3>)を収集して一覧化し、クリックで対象セクションへジャンプできるナビゲーションUI。スクロール位置を監視して現在読んでいるセクションをハイライトする「アクティブ追跡」を持つことが多い。
Breadcrumbとの違い:BreadcrumbはページをまたぐパンくずナビゲーションでURL階層を示す。Table of Contentsはページ内のセクションナビゲーション。
Tabsとの違い:Tabsはコンテンツを切り替えて表示する(一度に1パネル)。Table of Contentsはすべてのセクションが同一スクロール上に存在し、アンカーリンクで移動するだけ。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- 記事・ドキュメント・ブログ本文など長文コンテンツ(読了時間3分以上の目安)
- セクションが4つ以上あり、読者が特定のセクションを直接参照したい場合
- API仕様書・設定画面・マニュアルなど繰り返し参照される技術文書
- SEO的にリッチスニペット(目次ジャンプリンク)を生成したい場合
3.2 When NOT to use
- セクションが3つ以下の短いページ → スクロール量が少なく不要
- シングルページアプリケーションのチャート画面・ダッシュボード → セクション構造がない
- スマホ専用のシンプルなフォームやランディングページ → 縦長TOCが邪魔になる
3.3 代替UI(Alternatives)
- セクション数が少ない →
Tabs(コンテンツをパネルに分割) - アプリ内の大きなナビ →
Sidebar/App rail - 見出し3つ以下の補助ナビ →
Anchor link(テキストリンクのみ)
4. 設計判断の核(Decision Principles)
目次の役割は「今どこか」と「次に何があるか」を同時に伝えること——アクティブ追跡なき目次はただのリンクリストに過ぎない。
判断の優先順位:① アクティブ追跡 → ② 階層の可視化 → ③ 配置(サイドバー vs インライン) → ④ スムーズスクロール
- アクティブ追跡は必須:
IntersectionObserverでスクロール位置を監視し、現在表示中のセクションをハイライトする。これがないと目次としての価値が半減する - H2のみ or H2+H3まで:H4以下まで含めると項目が多すぎて目次自体が読みにくくなる。深さは最大2段階に絞る
- 長い見出しは省略しない:目次の見出しテキストは本文の見出しと完全一致させる(要約しない)。ユーザーが「目次に書いてある言葉が本文にない」と混乱する
- スムーズスクロールを使う:
scroll-behavior: smoothまたはJS制御で、ジャンプではなくスムーズに移動する(位置の変化を知覚させる)
5. 状態設計(States)
5.1 必須状態(Required)
- Default:全セクションをリスト表示
- Active(現在地):スクロール位置と一致するセクションをハイライト(
aria-current="location")
5.2 条件付き状態(Conditional)
- Hover:ホバー時の視覚フィードバック(色変化・下線)
- Collapsed:インライン型でアコーディオン折りたたみ時の状態
- Sticky(スクロール固定):スクロールしてもサイドバーに固定表示されている状態
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Default | ✅ | 全セクション一覧 |
| Active | ✅ | 現在読んでいる位置 |
| Hover | — | クリック可能であること |
| Collapsed | — | 目次の開閉状態 |
| Sticky | — | ページをスクロールしても常に見える |
6. バリエーション設計(Variants)
配置と用途で選ぶ。「機能」は同じで「コンテキスト」が変わる。
| バリアント | 目的 | 使用シーン |
|---|---|---|
| サイドバー固定型 | 常時表示・スクロール追跡 | PC幅のある記事・ドキュメント |
| インライン型 | 記事冒頭に埋め込む | 全幅レイアウト・モバイルファースト |
| フローティング型 | 画面端に固定 | ダッシュボード・長文エディタ |
| ミニマル型(チップ) | 3〜5セクションのコンパクトナビ | ランディングページ |
禁止パターン:TOCとパンくず(Breadcrumb)を同一エリアに縦積みしない → 「どこにいるか系UI」が2つ並んでユーザーが混乱する。Breadcrumbはヘッダー、TOCはサイドバーと配置を分ける。
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- アクティブ追跡なし:ジャンプできるだけで現在地が分からず、目次を開いても「どこを読んでいたか」分からない
- すべての見出し階層を表示:H2〜H5まで全部入れて項目が20件以上あり、目次自体がスクロールを必要とする
- スムーズスクロールなし:クリックした瞬間に画面がジャンプして位置の変化が分からず、ユーザーが迷子になる
7.1 Bad(典型3つ)
<a href="#section">をリスト化しただけでIntersectionObserverなし。今どこにいるか分からない- H2からH5まですべての見出しをTOCに含め、25項目のリストになっている
- モバイルで画面の60%を占める巨大なTOCが記事コンテンツの前に表示され、本文に到達するまでにスクロールが必要
7.2 Good(対になる3つ)
IntersectionObserverでスクロール位置を監視し、表示中のセクションにaria-current="location"と青いハイライトを付与- H2のみ、またはH2+H3(インデント付き)の2段階に絞ってTOCの項目を10件以内に収める
- モバイルではTOCをデフォルト非表示にしてアコーディオンで展開できるようにし、コンテンツが最初に見える
7.3 How to fix(手順)
IntersectionObserverを使って各見出し要素の表示状態を監視する- 表示中の見出しIDと一致するTOCアイテムに
aria-current="location"と視覚的ハイライトを付与する - H4以下の見出しをTOCから除外し、最大10項目程度に絞る
- モバイル幅では
<details>または Accordion でTOCをデフォルト折りたたみにする
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
- TOC内のリンクはすべて
Tabキーでフォーカス移動できること Enterでアンカージャンプが実行されること- ジャンプ先のセクション見出しにフォーカスが移動すること(
tabindex="-1"+focus()で対応)
Focus
- フォーカスリングを必ず表示する(
outlineを消さない) - ジャンプ後はスクロール先の見出し要素にフォーカスを移動させてキーボードユーザーの現在地を明示する
Screen Reader
<nav aria-label="目次">で目次ナビゲーションとして認識させる- アクティブ項目には
aria-current="location"を付与する - アコーディオン折りたたみTOCは
aria-expandedで開閉状態を伝える
<nav aria-label="目次">
<ul>
<li>
<a href="#intro" aria-current="location">はじめに</a>
</li>
<li>
<a href="#definition">定義</a>
</li>
</ul>
</nav>
Touch / Pointer
- TOCアイテムのタップ領域は最低 44×44px を確保する(
min-height: 44px) - サイドバー固定型はモバイルで画面を専有しないよう折りたたみ対応する
Contrast / Readability
- TOCテキストは本文テキストと同等のコントラスト比(4.5:1以上)を確保する
- アクティブ状態のハイライト色は背景とテキストのコントラストが十分なこと
10. 実装メモ(Implementation Notes)
IntersectionObserverで各<h2>・<h3>を監視し、isIntersectingがtrueになった最初の要素のIDをアクティブとして状態管理する- スクロールジャンプ後にキーボードユーザーがセクション内を操作できるよう、ジャンプ先の見出しに
tabindex="-1"を付与してelement.focus()を呼ぶ next/navigationのusePathname+useEffectでルート変更時にTOCアクティブ状態をリセットする- 折りたたみTOCは shadcn/ui の
Accordionコンポーネントで実装するとaria-expanded管理が自動化できる
11. 関連リンク
- 関連するUIデザイン原則: スキャンしやすさ (Scannability), 視覚的階層 (Visual Hierarchy), 情報密度 (Information Density)
- 用語集(定義): 視覚的階層 (Visual Hierarchy), 可読性 (Readability)
- 関連するUIコンポーネント(横): Breadcrumb(パンくずリスト), Sidebar(サイドバー), Tabs(タブ), Pagination(ページネーション)
12. まとめ
Table of Contentsの設計は「アクティブ追跡あり or なし」で読者体験が大きく変わります。迷ったら 4. 設計判断の核 に戻り、IntersectionObserver でのアクティブ追跡・H2+H3の2段階制限・モバイルでの折りたたみ対応の3点を確認してください。「ただのリンクリスト」にしないことが、ページ内ナビゲーションとしてのTOCの価値を最大化する最初の一歩です。