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 只是導航,不會替混亂的內容結構打掃房間。實作前先確認:
- 一篇文章有一個主要 H1
- 大章節用 H2,小節用 H3,層級不要從 H2 突然跳到 H4
- 每個目標標題都有唯一且穩定的
id - 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 只負責增強
- [ ] 目錄容器有
nav和aria-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。
