TOC(Table of Contents,文章目錄) 是把章節標題變成頁內連結的導覽區塊,讓讀者先看地圖、再跳到需要的段落。長文沒有目錄,讀者就得一路往下捲,像在網頁裡玩「找不同」——不同的是重點到底藏在哪裡。

這篇讀完,你會知道 TOC 對閱讀體驗與 SEO 能幫多少、如何用原生 HTML 做出穩定錨點,以及靜態網站、JavaScript 和 WordPress 各自適合什麼做法。

快速參考

項目說明
TOC 是什麼章節標題的頁內導覽清單,通常連到 #錨點
對 SEO 有幫助嗎沒有保證加分;清楚的標題結構 + 可爬取的 <a href> 才是重點
靜態站(11ty)建置時產生 HTML,本站用 [[toc]]
動態站JS 掃描 H2/H3,或 WordPress TOC 外掛
必備條件每個目標標題有唯一 id,TOC 的 href 與之對應

TOC 對讀者與 SEO 各幫什麼?

讀者體驗(主要價值)

一份好的 TOC 至少有三個用途:

  • 讓讀者快速掃過文章範圍,判斷內容是否值得讀
  • 讓讀者直接跳到需要的章節,少滑幾個螢幕
  • 讓讀者複製 網址#錨點,把特定段落分享給別人

SEO:務實版

Google 沒有保證「加入 TOC 就會排名更高」。比較可靠的做法:

  • 用一個 H1,再用 H2、H3 分出章節
  • 使用真正的 <a href="#section-id">,而不是只有 JavaScript 點擊
  • 連結文字描述目標內容,不要全部叫「點這裡」

Google 文件指出,通常需要有 href<a> 元素,搜尋系統才容易擷取連結。搜尋結果是否顯示頁內跳轉連結,仍由系統自動判斷,不能手動保證。

另外,頁內跳轉(jump link)和 sitelinks 不是同一件事。Google 已於 2024 年 11 月 21 日起移除搜尋結果中的 sitelinks search box,但這不等於一般 sitelinks 或頁內錨點消失。

先把標題和錨點做好

TOC 只是導航,不會替混亂的內容結構打掃房間。實作前先確認:

  1. 一篇文章有一個主要 H1
  2. 大章節用 H2,小節用 H3,層級不要從 H2 突然跳到 H4
  3. 每個目標標題都有唯一且穩定的 id
  4. TOC 的 href 必須和目標標題的 id 完全相同
<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>
		<p>這裡是文章簡介。</p>
	</section>
	<section id="setup">
		<h2>開始實作</h2>
		<p>這裡是實作內容。</p>
	</section>
</article>

id 不能在同一頁重複。若兩個標題都叫「結語」,產生器需處理碰撞,例如輸出 結語結語-1

三種 TOC 實作方式

方式適合情境優點注意
A. 建置時靜態產生11ty、Hugo、Astro無 JS 依賴、SEO 友善、版面穩定需在建置流程設定
B. JavaScript 動態掃描SPA、需摺疊/高亮目前章節互動彈性高不應成為唯一導航來源
C. WordPress 外掛/區塊WP 部落格免寫 code慎選,避免載入過多腳本

A. 建置時產生靜態 TOC(11ty)

Markdown 內文放標記:

[[toc]]

建置工具讀取標題,輸出 HTML 清單與錨點。本站 [[toc]]markdown-it-table-of-contents 處理,目前設定只列出 H2。H3 會出現在正文,但不會自動列進目錄——這是建置設定,不是 Markdown 的宇宙定律。

B. JavaScript 動態掃描標題

適合需要摺疊目錄、標示目前章節的頁面。建議用 createElement 而非 innerHTML,避免把標題文字當 HTML 解析:

<nav id="table-of-contents" aria-label="文章目錄">
	<h2>目錄</h2>
	<ol id="toc-list"></ol>
</nav>
const tocList = document.querySelector('#toc-list');
const headings = document.querySelectorAll('article h2');
const usedIds = new Set();

headings.forEach((heading, index) => {
	let id = heading.id || `section-${index + 1}`;
	let suffix = 1;

	while (usedIds.has(id)) {
		id = `${heading.id || `section-${index + 1}`}-${suffix}`;
		suffix += 1;
	}

	heading.id = id;
	usedIds.add(id);

	const item = document.createElement('li');
	const link = document.createElement('a');
	link.href = `#${id}`;
	link.textContent = heading.textContent;
	item.append(link);
	tocList.append(item);
});

若內容在這段程式執行後才載入,需把建立目錄的時機放到內容完成後。

C. WordPress 外掛或區塊

選外掛時先看:

  • 能否排除不想出現的標題(如「參考資料」)
  • 輸出是否為真正的 <a href="#...">
  • 能否處理重複標題並產生唯一 ID
  • 手機版是否容易操作,且不載入不必要的腳本

發布前檢查清單

  • [ ] H1、H2、H3 層級符合內容結構
  • [ ] 每個 TOC 連結都有 href="#...",目標標題有唯一 id
  • [ ] 目錄文字和目標標題一致
  • [ ] 靜態站優先建置時輸出;JS 只負責增強
  • [ ] 目錄容器有 navaria-label
  • [ ] 手機版容易收合或掃讀
  • [ ] 已實際點過每個連結,也測過重新整理後的 #錨點

常見問題

TOC 一定要放在文章最前面嗎?

長文通常放在引言後最方便掃描;桌面版也可固定在側欄。重點是目錄在 HTML 中真實存在,且連結能直接跳到內容。

中文標題的 id 怎麼產生?

可用中文 ID、拼音或其他穩定 slug。重點是規則穩定、結果不重複,且 TOC 與標題共用同一套規則。本站允許中文 slug,TOC 與標題 ID 共用自訂 slugify。

要不要把 H3 也放進目錄?

看文章長度。小節很多時,H3 會讓目錄變成另一篇文章;小節較少時,列出 H3 能幫助定位。本站目前只輸出 H2;若要 H3 目錄,需調整建置設定。

TOC 會不會和外掛衝突?

可能。最常見是兩個工具同時替標題產生 ID,導致連結失效。建議由單一工具負責 ID,建置後檢查 HTML 是否有重複 ID。

結語

TOC 的核心價值:讓讀者更快找到重點,也讓頁面結構更容易被理解。靜態站優先選建置時產生的原生 HTML;需要高亮、摺疊時再讓 JavaScript 上場;WordPress 則慎選外掛。

延伸閱讀:11ty 入門PageSpeed 與 Core Web Vitals

參考資料