Markdown 錨點語法完全指南
寫長文件的時候,你肯定遇過這種需求:開頭放個目錄,點擊某個章節名稱就直接跳到對應位置。這就是 markdown 錨點(anchor)做的事。
說實話這個功能本身不難,但坑在於——不同平台對錨點的處理方式差別挺大的。GitHub 上一套規則,CSDN 上又一套,Pandoc 又不一樣。這篇文章就把 markdown anchor 的各種用法和平台差異都整理清楚。
什麼是 Markdown 錨點
錨點的概念來自 HTML。在網頁裡,給某個位置設一個 id,然後用 #id 格式的連結就能跳到那個位置。Markdown 錨點做的事情一樣,只不過寫法上做了一些簡化。
舉個最直白的例子:
[跳轉到安裝指南](#installation)
## Installation
這裡寫安裝步驟...點擊「跳轉到安裝指南」這個連結,頁面就會捲動到 ## Installation 這個標題的位置。大多數 Markdown 渲染器會自動根據標題文字生成對應的 ID,你只需要用 # 加上這個 ID 就能連結過去。
順便說一句,如果你還想了解更廣泛的連結寫法(比如外部連結、圖片連結),可以看看 Markdown 連結語法這篇文章。本文只聚焦錨點這一種特殊的連結方式。
標題自動生成錨點
這是最常用的方式,也是大多數平台的預設行為——你寫一個標題,渲染器自動給它生成一個 ID,然後你就能用 #id 跳過去。
基本用法
## 快速開始
點擊[這裡](#快速開始)回到開頭。在上面這個例子中,## 快速開始 會被渲染成一個帶有 id 屬性的 HTML 標題,你用 #快速開始 就能連結到它。
不過,不同平台生成 ID 的規則不太一樣。我把自己常用的幾個平台整理了一個對照表:
| 規則 | GitHub | GitLab | CSDN | Pandoc |
|---|---|---|---|---|
| 英文標題 | Getting Started → getting-started | 同 GitHub | 同 GitHub | 同 GitHub |
| 空格處理 | 替換為 - | 同左 | 同左 | 同左 |
| 大寫字母 | 轉小寫 | 同左 | 同左 | 同左 |
| 特殊字符 | 移除(保留 -) | 同左 | 同左 | 同左 |
| 中文標題 | 保留原字符 | 保留原字符 | 保留原字符 | 保留原字符 |
| 重複標題 | 追加 -1、-2 | 同左 | 同左 | 同左 |
GitHub 的標題 ID 生成規則
GitHub 是大家用得最多的 Markdown 渲染平台之一,它的規則比較有代表性:
## What's New? → id="whats-new"
## Getting Started → id="getting-started"
## Let's try it! → id="lets-try-it"
## 3. Installation → id="3-installation"規則總結一下就是:全轉小寫,空格變連字符,標點符號去掉(連字符本身保留),數字保留。如果兩個標題生成了一樣的 ID,後面那個會自動追加 -1、-2 這樣遞增的後綴。
我之前在 GitHub 上寫一個專案的 README,裡面有兩個三級標題都叫「配置」,一個在 Linux 章節,一個在 macOS 章節。結果兩個都生成了 #配置,GitHub 就自動把第二個改成了 #配置-1。當時我還納悶為什麼連結跳錯了位置,後來才發現是重複標題的問題。所以如果你的文件裡有同名的標題,最好手動給其中一個加個區分。
手動建立錨點
標題自動生成的錨點能覆蓋大部分場景,但有時候你想跳到的位置並不是一個標題——比如表格中間、程式碼區塊旁邊、或者一段話的某個位置。這時候就需要手動建立錨點了。
用 HTML 的 <a> 或 <span> 標籤
Markdown 本身沒有專門建立錨點的語法,但幾乎所有 Markdown 渲染器都支援嵌入 HTML。所以最通用的方法就是用 HTML 標籤的 id 屬性:
<a id="important-note"></a>
> 這是一段特別重要的注意事項,我想讓讀者能直接跳到這裡。
點擊[這裡](#important-note)跳到上面的注意事項。<a> 和 <span> 都可以,效果一樣。我一般用 <a>,因為語意上更準確(它就是一個錨點)。有些人喜歡用 <div id="xxx">,也行,但 <div> 是區塊級元素,在某些場景下會影響排版。
需要注意的是,CSDN 的編輯器會把 <a> 標籤的 name 屬性過濾掉,只保留 id 屬性。所以如果你要在 CSDN 上用,務必用 id 而不是 name。
自定義標題錨點 ID
有些 Markdown 擴展支援直接給標題指定自定義 ID,這樣就不依賴自動生成的規則了。
{#id} 語法
這是最常見的一種寫法,源自 Markdown Extra 和 Pandoc:
## 安裝步驟 {#install-steps}
詳細安裝內容...
[跳到安裝步驟](#install-steps){#install-steps} 寫在標題文字後面,用花括號包起來。這樣不管標題本身是什麼文字,生成的錨點 ID 都是 install-steps。
支援的渲染器包括:
- Pandoc:完整支援
- Kramdown(Jekyll 預設):完整支援
- PHP Markdown Extra:完整支援
- R Markdown:支援
- GitHub:不支援,
{#id}會被當作標題文字的一部分
GitHub 不支援 {#id} 這一點很多人踩坑。如果你想給 GitHub 上的文件用自定義錨點,只能用前面說的 HTML <a id="xxx"> 方式。
錨點連結的完整語法
了解了怎麼建立錨點之後,來看看怎麼寫連結指向它們。
頁內跳轉
最基本的用法,在當前頁面內跳轉:
[跳到常見問題](#常見問題)
...(很多內容)...
## 常見問題連結地址就是 # 加上目標的 ID 值,不需要寫頁面路徑。
跨頁面跳轉
錨點不僅可以跳當前頁面的位置,還能跳到另一個頁面的某個位置:
[查看另一篇文章的安裝章節](./installation.md#linux)
[查看官網的 API 文件](https://example.com/docs#api-reference)寫法就是在 URL 後面直接拼 #id。對本機 Markdown 檔案,用相對路徑加 #;對網頁 URL,也是直接追加 #。
我之前在寫一個系列教學的時候,每篇文章開頭都放了一個「上一篇 / 下一篇」的導航,同時還有個連結直接跳到下一篇的特定章節。這種跨頁面錨點在多文件專案裡特別好用。
用 HTML 的 <a> 標籤寫連結
雖然不常用,但你也可以用 HTML 的方式寫錨點連結:
<a href="#常見問題">跳到常見問題</a>效果跟 Markdown 連結語法一樣,只是在某些不支援 Markdown 錨點的平台上,HTML 寫法反而能正常工作。
平台相容性差異
這是寫 markdown anchor 最讓人頭痛的部分。我把自己實際用過的幾個平台的關鍵差異列出來:
| 特性 | GitHub | GitLab | CSDN | Jekyll | Pandoc |
|---|---|---|---|---|---|
| 標題自動 ID | ✅ | ✅ | ✅ | ✅ | ✅ |
{#id} 自定義 | ❌ | ✅ | ❌ | ✅ | ✅ |
<a id=""> 手動 | ✅ | ✅ | ✅(僅 id) | ✅ | ✅ |
<a name=""> | ❌ | ✅ | ❌(被過濾) | ✅ | ✅ |
| 跨頁面錨點 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 中文標題 ID | 保留中文 | 保留中文 | 保留中文 | 取決於設定 | 保留中文 |
從這個表裡可以看出一個規律:用 <a id="xxx"> 的方式是最通用的,在所有平台上都能工作。如果你不確定目標平台支援什麼,就用這種方式。
常見問題與除錯
錨點連結不生效
這是最常遇到的問題。檢查以下幾點:
ID 匹配問題:連結裡的 ID 必須和目標 ID 完全一致,包括大小寫。
#Getting-Started和#getting-started是不同的。平台不支援:確認你用的平台是否支援標題自動生成 ID。有些舊的 Markdown 編輯器不會生成。
渲染後查看:錨點只在渲染後的 HTML 中有效,在 Markdown 原始碼裡直接看是不會有跳轉效果的。如果你的編輯器支援即時預覽,切到預覽模式試試。
空格和特殊字符:如果你連結的是一個帶空格或特殊字符的標題,記得按平台的規則轉換。GitHub 上
## Hello World!對應的是#hello-world,不是#hello-world!。
中文標題的錨點怎麼寫
中文標題的錨點在 GitHub、GitLab、CSDN 上基本都是直接保留中文字符:
## 使用說明
[跳到使用說明](#使用說明)但這裡有個小陷阱:有些渲染器會把中文標點去掉,有些會保留。比如 ## 安裝(推薦) 這個標題,有的平台生成 #安裝推薦(去掉了括號),有的生成 #安裝(推薦)(保留括號)。如果你發現中文標題的錨點不工作,最穩妥的辦法是在瀏覽器裡打開渲染後的頁面,右鍵檢查元素,看看實際生成的 id 值到底是什麼。
重複標題怎麼處理
前面提到過,如果同一個頁面裡有多個相同的標題,大多數平台會給後面的追加數字後綴:
## 配置 → #配置
## 配置 → #配置-1
## 配置 → #配置-2但這不是所有平台都這樣處理。所以最好還是避免同名標題,或者用自定義錨點來區分。
實戰:給文章加一個可點擊的目錄
學完了錨點的各種寫法,來做一個實際的東西——手動給文章建立一個目錄,點擊每個條目就能跳到對應章節。
## 目錄
- [簡介](#簡介)
- [安裝](#安裝)
- [配置](#配置)
- [常見問題](#常見問題)
## 簡介
這裡是簡介的內容...
## 安裝
安裝步驟...
## 配置
配置方法...
## 常見問題
Q&A...就這麼簡單。用 Markdown 列表 + 錨點連結就行。
如果你的文件很長,還可以在每個章節的末尾加一個「返回頂部」的連結:
## 簡介
簡介內容...
[↑ 返回目錄](#目錄)
## 安裝
安裝步驟...
[↑ 返回目錄](#目錄)說實話語法本身沒幾行,但坑都在細節裡。不同平台的行為差異、中文標題的 ID 生成規則、重複標題的後綴處理——這些才是真正讓人抓狂的地方。我的建議是:先確定你主要用什麼平台,然後記住那個平台的規則就夠了。如果要跨平台,就用 <a id="xxx"> 這個最通用的方案。
參考來源
- GitHub Flavored Markdown Spec — GitHub 官方 Markdown 規範
- Markdown Guide — Hacks — Markdown Guide 專案,錨點解決方案章節
- CommonMark Spec Discussion: Anchors in Markdown — CommonMark 規範層面關於錨點的討論
- Pandoc User's Guide — Heading Identifiers — Pandoc 官方文件中的標題 ID 說明
- markdown-it-anchor (npm) — 開發者側的錨點渲染方案參考