長文沒有目錄,讀者只能一路往下捲;搜尋引擎也較難快速掌握章節結構。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 規範

無論哪種方案,先把內容結構做好:

  1. 一篇文一個 H1(通常是標題,模板已處理)
  2. 章節用 H2,小節用 H3,不要跳級
  3. 每個要進目錄的標題都有穩定 id(可手動或建置時 slugify)
  4. TOC 連結用 <a href="#id">,不要只靠 JS scrollIntoView 卻沒有真實 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
  • [ ] 加上 navaria-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