Markdown 列表語法完全指南

Markdown 列表是什麼

寫文件的時候,列表是最常用的排版方式之一——不管是列要點、排步驟,還是做待辦清單,都離不開它。Markdown 提供了幾種列表類型:無序列表(bullet list)、有序列表(numbered list)、巢狀列表(nested list)和任務列表(task list)。

這篇教學會從最基礎的寫法講起,到巢狀規則、縮排陷阱,再到不同平台的相容性差異,爭取讓你看完這篇就夠用了。

無序列表(Unordered List / Bullet List)

無序列表就是每一項前面帶個圓點的列表,也有人叫它「項目符號列表」或「bullet points」。

語法很簡單,在行首寫 -*+,加一個空格,再寫內容就行:

- 蘋果
- 香蕉
- 橘子

渲染效果:

  • 蘋果
  • 香蕉
  • 橘子

三種符號你可以任選一種,效果完全一樣:

* 用星號也行
+ 用加號也可以
- 用減號當然沒問題

不過建議同一篇文件裡只用一種。說實話這是個人習慣問題,但混著用看著確實有點亂,而且部分解析器會把不同符號開頭的項目識別成不同的列表區塊,中間自動插入間距。我自己的習慣是全部用 -,因為它和其他 Markdown 語法衝突最少(* 可能和粗體斜體混淆)。

有序列表(Ordered List / Numbered List)

有序列表的每一項前面是數字,適合寫步驟、排名這類有順序要求的內容:

1. 打開編輯器
2. 新建文件
3. 開始寫作

渲染效果:

  1. 打開編輯器
  2. 新建文件
  3. 開始寫作

這裡有個很多人不知道的細節:數字其實不影響最終的編號順序。Markdown 解析器會按照列表項出現的順序自動編號。所以下面這樣寫,渲染結果跟上面完全一樣:

1. 打開編輯器
1. 新建文件
1. 開始寫作

但有個例外——起始數字是有意義的。如果你從 3 開始寫,列表會從 3 開始編號:

3. 第三步
4. 第四步
5. 第五步

這個行為是 CommonMark 規範明確定義的,GitHub、Obsidian、VS Code 等主流平台都遵循這個規則。

一個實用建議:如果你以後可能會在中間插入或刪除某一項,全部用 1. 來寫會方便很多——改一處不用把後面所有數字都重新排一遍。

對了,有序列表的標記符必須用句號 .,不能用括號 )。像 1) 這種寫法在部分解析器裡不被支援,盡量別用。

巢狀列表(Nested List / Sublist)

巢狀列表就是列表裡面再套一層列表,用來表達層級關係。寫法是透過縮排來表示層級。

縮排規則

縮排可以用空格或 Tab,關鍵點是:

  • 空格縮排 2-4 個都可以被識別
  • Tab 縮排 1 個等於 4 個空格
  • 子列表的標記符必須比父列表的內容多縮排至少 1 個空格
- 水果
  - 蘋果
    - 紅富士
    - 青蘋果
  - 香蕉
- 蔬菜
  - 白菜
  - 蘿蔔

渲染效果:

  • 水果
    • 蘋果
    • 紅富士
    • 青蘋果
    • 香蕉
  • 蔬菜
    • 白菜
    • 蘿蔔

2 空格 vs 4 空格

這裡有坑。CommonMark 規範對無序列表的定義是:縮排 1-3 個空格都算子列表。但不同平台的行為不完全一致:

縮排空格數GitHubObsidianVS Code
2 空格正常渲染正常渲染正常渲染
3 空格正常渲染正常渲染正常渲染
4 空格正常渲染正常渲染正常渲染

我自己實測下來,2 空格在絕大多數平台上都能正常工作,而且看起來更緊湊,也是 GitHub 官方文件推薦的做法。之前有段時間我習慣用 4 空格,後來在一個專案裡跟別人協作時發現他們全用 2 空格,混在一起特別難看,就統一改成 2 了。

順便提一句,如果你在列表裡縮排超過 4 個空格(相對於列表標記符),有的解析器會把它當成程式碼區塊來處理——這也就是為什麼巢狀太深的時候,文字突然變成了等寬字體的程式碼。Reddit 上就有人吐槽過這個問題。

有序 + 無序混合巢狀

有序列表和無序列表可以互相巢狀,比如:

1. 準備食材
   - 麵粉 500g
   - 雞蛋 3 個
   - 牛奶 250ml
2. 開始製作
   1. 把麵粉倒入盆中
   2. 打入雞蛋
   3. 倒入牛奶攪拌均勻
3. 烘烤

這種混合巢狀在寫操作步驟或技術文件時特別好用。

任務列表(Task List / Checklist)

任務列表也有人叫「待辦清單」或「checkbox list」,是 GitHub Flavored Markdown(GFM)的擴展語法。在普通列表的基礎上加上 [ ][x] 就行:

- [x] 完成需求文件
- [x] 審查程式碼
- [ ] 部署測試環境
- [ ] 上線發布

渲染效果:

  • [x] 完成需求文件
  • [x] 審查程式碼
  • [ ] 部署測試環境
  • [ ] 上線發布

注意幾點:

  • [ ] 裡面是一個空格,表示未完成
  • [x] 裡面是小寫字母 x,表示已完成(大寫 X 大多數平台也支援)
  • 方括號前面是 -,和普通列表的標記符一樣

任務列表在 GitHub 的 Issues 和 PR 中特別常見——你可以在 Markdown 裡直接勾選和取消勾選,GitHub 會自動更新原始檔案。Obsidian 和部分編輯器也支援這個互動。

不過要注意,任務列表屬於 GFM 擴展語法,不是所有 Markdown 解析器都支援。原始的 Markdown 規範裡沒有這個東西,在一些舊版的渲染器上可能顯示為純文字。

列表中嵌入其他元素

這個功能很多人不知道,但確實很實用。你可以在列表項之間插入段落、程式碼區塊、引用甚至圖片——只要縮排對了就行。

列表中加段落

在列表項下面空一行,然後縮排對齊到文字內容的位置:

- 第一點

  這是第一點的補充說明,縮排到和「第」字對齊的位置。

- 第二點

列表中加程式碼區塊

在列表裡嵌入程式碼區塊需要縮排 4 個空格(相對於標記符)或 1 個 Tab,加上圍欄標記:

1. 安裝依賴:

   ```bash
   npm install markdown-it
  1. 引入模組

列表中加引用

- 一個重要的事實

  > 這段引用和上面的文字屬於同一個列表項

- 另一個要點

說實話,這種巢狀寫法在實際用的時候很容易把縮排搞亂。我的建議是:如果巢狀超過兩層,考慮用標題來分割內容,別硬塞在列表裡。

常見問題與踩坑經驗

列表之間被意外合併

如果你寫了兩個列表,中間沒有其他內容,有些解析器會把它們合併成一個。解決辦法是在兩個列表之間加一行不是列表的內容(比如一行普通文字或 <!-- --> 註解):

- 列表 A 第一項
- 列表 A 第二項

<!-- -->

- 列表 B 第一項
- 列表 B 第二項

有序列表不想從 1 開始

前面說過起始數字是有意義的,但你想從特定數字開始時,直接寫那個數字就行。不過要注意,不是所有渲染器都支援非 1 起始——有些會忽略起始數字直接從 1 開始。

巢狀太深變成程式碼區塊

這是我之前踩過的坑。在寫一個多層級的大綱時,巢狀到第四層發現文字突然變成了等寬字體。原因就是縮排超過了 4 個空格(相對於最外層標記符),解析器把它當成了縮排式程式碼區塊。解決辦法是減少巢狀層級,或者用 HTML 的 <ul> / <ol> 標籤來處理深層巢狀。

字母列表或羅馬數字列表

標準 Markdown 不支援 a. b. c.i. ii. iii. 這種格式的有序列表。如果你需要的話,有幾個方案:

  • 用 HTML:<ol type="a"> 可以產生字母列表
  • 用 Pandoc:它支援 fancy_lists 擴展,可以用 a.A.i.I. 等標記符
  • 在 GitHub 和大多數平台上,目前只能用純數字

列表類型速查表

列表類型標記符範例適用場景
無序列表- / * / +- 蘋果並列要點
有序列表數字.1. 第一步步驟/排名
巢狀列表縮排 2-4 空格- 子項層級關係
任務列表- [ ] / - [x]- [x] 完成待辦清單

不同平台相容性對比

功能GitHubObsidianVS CodeTypora
-/*/+ 三種符號支援支援支援支援
有序列表自動編號支援支援支援支援
非標準起始數字支援支援支援支援
巢狀列表(2空格)支援支援支援支援
巢狀列表(4空格)支援支援支援支援
任務列表支援支援預覽支援支援
列表中嵌入程式碼區塊支援支援支援支援
字母/羅馬數字列表不支援不支援不支援不支援

參考來源

  1. CommonMark Spec - Lists — CommonMark 官方列表教學
  2. Markdown Guide - Basic Syntax — Markdown Guide 列表語法參考
  3. GitHub Docs - Lists — GitHub 官方列表語法文件
  4. jmmv.dev - Markdown Lists — Markdown 列表格式化最佳實踐
  5. Markdown Guide - Task Lists — Markdown Guide 任務列表擴展語法