長文沒有目錄,讀者只能一路往下捲;搜尋引擎也較難快速掌握章節結構。Table of Contents(TOC) 用錨點把標題變成可跳轉清單,同時改善體驗與可解析的頁面結構。
本站文章開頭的目錄,就是建置時用 Markdown/11ty 產生的靜態 TOC。下面說明為什麼重要、三種實作路線,以及 2026 年常見迷思。
TOC 對使用者與 SEO 有什麼用
使用者體驗
- 快速掃過大綱,決定要不要往下讀
- 手機上少滑幾屏就能到目標段落
- 降低「找不到重點就離開」的機率
對搜尋的幫助(務實版)
Google 不會因為你放了 TOC 就保證加分,但良好結構通常伴隨這些可觀察現象:
- 標題層級清楚(單一 H1,其下 H2/H3 不亂跳)
- 頁內有原生 HTML 錨點連結(
href="#section-id"),爬蟲容易跟隨 - 長文較可能出現「跳到頁內段落」的搜尋結果連結(演算法決定,無法手動保證)
已過時的說法:「加 WebSite SearchAction 就能出 Sitelinks 搜尋框」。Google 已於 2024-11 起不再顯示該視覺元素(官方說明)。一般 sitelinks(網域下其他頁連結)與頁內 jump links 是不同機制,不要混為一談。
實作前:標題與 ID 規範
無論哪種方案,先把內容結構做好:
- 一篇文一個 H1(通常是標題,模板已處理)
- 章節用 H2,小節用 H3,不要跳級
- 每個要進目錄的標題都有穩定
id(可手動或建置時 slugify) - TOC 連結用
<a href="#id">,不要只靠 JSscrollIntoView卻沒有真實 hash
<article>
<h1>文章標題</h1>
<nav aria-label="文章目錄">
<ol>
<li><a href="#intro">簡介</a></li>
<li><a href="#setup">安裝</a></li>
</ol>
</nav>
<section id="intro">
<h2>簡介</h2>
…
</section>
<section id="setup">
<h2>安裝</h2>
…
</section>
</article>
三種實現方式對比
| 方案 | 優點 | 缺點 | 適合 |
|---|---|---|---|
A. 建置時靜態 TOC(Markdown/11ty [[toc]]) |
零前端 JS、HTML 直接可爬、CLS 風險低 | 需建置流程 | 靜態站、技術部落格 |
| B. 前端 JS 掃描標題 | 彈性高、可摺疊/高亮目前章節 | 依賴 JS;實作不好會影響 CLS/無 JS 使用者 | SPA、動態 CMS 主題 |
| C. WordPress 外掛 | 後台開關、樣式現成 | 多載 CSS/JS;要挑輕量外掛 | WordPress 內容站 |
A. 靜態站(本站做法)
在 Markdown 引言後放一行:
[[toc]]
建置時由 markdown-it(或同類外掛)依標題產生清單。優點是輸出就是普通 HTML,對 SEO 與無障礙都友善。
B. 純前端動態 TOC(教學範例)
適合沒有建置步驟、只想在靜態 HTML 示範的情況。
<div id="table-of-contents">
<h2>目錄</h2>
<ol id="toc-list"></ol>
</div>
#table-of-contents {
border: 1px solid #ccc;
padding: 1rem;
margin: 1.5rem 0;
}
#toc-list a {
text-decoration: none;
}
#toc-list a:hover {
text-decoration: underline;
}
document.addEventListener('DOMContentLoaded', () => {
const tocList = document.getElementById('toc-list');
const article = document.querySelector('article') || document.body;
const headers = article.querySelectorAll('h2, h3');
headers.forEach((header, index) => {
if (!header.id) {
header.id = `section-${index}`;
}
const li = document.createElement('li');
const a = document.createElement('a');
a.href = `#${header.id}`;
a.textContent = header.textContent;
if (header.tagName === 'H3') {
li.style.marginLeft = '1rem';
}
li.appendChild(a);
tocList.appendChild(li);
});
});
注意:若 SEO 是優先考量,最好在伺服器或建置階段就輸出目錄,JS 只負責「目前章節高亮」這類加強功能。
C. WordPress
常見選擇:
- Easy Table of Contents:功能完整,記得關閉不需要的動畫與自動插入範圍
- Rank Math/Yoast 等 SEO 外掛有時內建 TOC 區塊:用區塊編輯器插入即可
挑選原則:盡量少額外腳本、支援錨點、可排除特定標題、行動版可摺疊。
完整最小示範頁
你也可以開啟 CSS Counter 列表示範頁,查看實際的列表編號效果。
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TOC 示範</title>
<style>
#table-of-contents { border: 1px solid #ccc; padding: 1rem; }
#toc-list { padding-left: 1.25rem; }
section { min-height: 60vh; }
</style>
</head>
<body>
<div id="table-of-contents">
<h2>目錄</h2>
<ol id="toc-list"></ol>
</div>
<article>
<h1>示範文章</h1>
<section><h2>簡介</h2><p>…</p></section>
<section><h2>實作</h2><p>…</p></section>
<section><h2>結語</h2><p>…</p></section>
</article>
<script>
document.addEventListener('DOMContentLoaded', () => {
const tocList = document.getElementById('toc-list');
document.querySelectorAll('article h2').forEach((header, i) => {
header.id = header.id || `h-${i}`;
const li = document.createElement('li');
li.innerHTML = `<a href="#${header.id}">${header.textContent}</a>`;
tocList.appendChild(li);
});
});
</script>
</body>
</html>

2026 最佳實踐 Checklist
- [ ] 標題層級正確,目錄文字與 H2/H3 一致(利於長尾語意)
- [ ] 使用原生
#錨點,可複製網址直達段落 - [ ] 靜態優先;JS 只做增強
- [ ] 預留 TOC 區塊高度或建置時渲染,避免 CLS
- [ ] 加上
nav/aria-label,方便輔助科技 - [ ] 行動版可摺疊,避免目錄比本文還長
- [ ] 不要期待「Sitelinks 搜尋框」;把力氣放在結構與內容品質
結構化資料(Article 等)可輔助理解頁面,但不能取代清楚的標題與錨點。Jump links 是否出現在 SERP 由 Google 演算法決定。
常見問題
Q:TOC 一定要放文首嗎?
A:長文建議文首;也可側欄固定(桌面)。重點是連結真實存在於 HTML。
Q:中文標題的 id 怎麼辦?
A:用可讀的 slug(允許中文或轉拼音/hash)。本站用自訂 slugify,讓 TOC 與標題 id 一致。
Q:會不會和廣告/錨點外掛衝突?
A:可能。統一由一處產生 id,避免兩個外掛各改一次標題。
結語
TOC 的價值很單純:讓人與爬蟲都更快看懂文章結構。2026 年實務上,優先選「建置時靜態輸出 + 原生錨點」;WordPress 則挑輕量外掛;純 JS 方案留給需要互動增強的場景。
若你走靜態站路線,可接續閱讀:11ty 入門、PageSpeed 與 Core Web Vitals。