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 的規則不太一樣。我把自己常用的幾個平台整理了一個對照表:

規則GitHubGitLabCSDNPandoc
英文標題Getting Startedgetting-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 最讓人頭痛的部分。我把自己實際用過的幾個平台的關鍵差異列出來:

特性GitHubGitLabCSDNJekyllPandoc
標題自動 ID
{#id} 自定義
<a id=""> 手動✅(僅 id)
<a name="">❌(被過濾)
跨頁面錨點
中文標題 ID保留中文保留中文保留中文取決於設定保留中文

從這個表裡可以看出一個規律:<a id="xxx"> 的方式是最通用的,在所有平台上都能工作。如果你不確定目標平台支援什麼,就用這種方式。

常見問題與除錯

錨點連結不生效

這是最常遇到的問題。檢查以下幾點:

  1. ID 匹配問題:連結裡的 ID 必須和目標 ID 完全一致,包括大小寫。#Getting-Started#getting-started 是不同的。

  2. 平台不支援:確認你用的平台是否支援標題自動生成 ID。有些舊的 Markdown 編輯器不會生成。

  3. 渲染後查看:錨點只在渲染後的 HTML 中有效,在 Markdown 原始碼裡直接看是不會有跳轉效果的。如果你的編輯器支援即時預覽,切到預覽模式試試。

  4. 空格和特殊字符:如果你連結的是一個帶空格或特殊字符的標題,記得按平台的規則轉換。GitHub 上 ## Hello World! 對應的是 #hello-world,不是 #hello-world!

中文標題的錨點怎麼寫

中文標題的錨點在 GitHub、GitLab、CSDN 上基本都是直接保留中文字符:

## 使用說明

[跳到使用說明](#使用說明)

但這裡有個小陷阱:有些渲染器會把中文標點去掉,有些會保留。比如 ## 安裝(推薦) 這個標題,有的平台生成 #安裝推薦(去掉了括號),有的生成 #安裝(推薦)(保留括號)。如果你發現中文標題的錨點不工作,最穩妥的辦法是在瀏覽器裡打開渲染後的頁面,右鍵檢查元素,看看實際生成的 id 值到底是什麼。

重複標題怎麼處理

前面提到過,如果同一個頁面裡有多個相同的標題,大多數平台會給後面的追加數字後綴:

## 配置           → #配置
## 配置           → #配置-1
## 配置           → #配置-2

但這不是所有平台都這樣處理。所以最好還是避免同名標題,或者用自定義錨點來區分。

實戰:給文章加一個可點擊的目錄

學完了錨點的各種寫法,來做一個實際的東西——手動給文章建立一個目錄,點擊每個條目就能跳到對應章節。

## 目錄

- [簡介](#簡介)
- [安裝](#安裝)
- [配置](#配置)
- [常見問題](#常見問題)

## 簡介

這裡是簡介的內容...

## 安裝

安裝步驟...

## 配置

配置方法...

## 常見問題

Q&A...

就這麼簡單。用 Markdown 列表 + 錨點連結就行。

如果你的文件很長,還可以在每個章節的末尾加一個「返回頂部」的連結:

## 簡介

簡介內容...

[↑ 返回目錄](#目錄)

## 安裝

安裝步驟...

[↑ 返回目錄](#目錄)

說實話語法本身沒幾行,但坑都在細節裡。不同平台的行為差異、中文標題的 ID 生成規則、重複標題的後綴處理——這些才是真正讓人抓狂的地方。我的建議是:先確定你主要用什麼平台,然後記住那個平台的規則就夠了。如果要跨平台,就用 <a id="xxx"> 這個最通用的方案。

參考來源

  1. GitHub Flavored Markdown Spec — GitHub 官方 Markdown 規範
  2. Markdown Guide — Hacks — Markdown Guide 專案,錨點解決方案章節
  3. CommonMark Spec Discussion: Anchors in Markdown — CommonMark 規範層面關於錨點的討論
  4. Pandoc User's Guide — Heading Identifiers — Pandoc 官方文件中的標題 ID 說明
  5. markdown-it-anchor (npm) — 開發者側的錨點渲染方案參考