符號清單與三種項目符號

符號清單的寫法是:一個符號、一個空格,然後是你的文字。Markdown 接受三種符號,效果完全相同:

- 濃縮咖啡
- 可塔多
- 平白咖啡

* 濃縮咖啡
* 可塔多
* 平白咖啡

+ 濃縮咖啡
+ 可塔多
+ 平白咖啡
重點摘要
  • 三種項目符號渲染結果一樣,挑連字號用到底就好,中途別換。
  • 編號清單第一個數字之後的數字都會被忽略,所以全部寫 1. 在 Git 裡更安全。
  • 巢狀縮排的訣竅是:把子項目符號對齊到父項目文字的第一個字底下。
  • 清單裡多出一行空行,整份清單都會變鬆散,行距全部被撐開。

三種寫法產生一模一樣的清單,所以請用連字號。它不必按 Shift、掃視原始碼時不會跟 *斜體* 混淆,也是 Prettier 等格式化工具統一轉換的目標,更是完整 Markdown 指南全篇採用的符號。

兩條沒得商量的規則

第一,符號後面的空格是必要的。寫成 -濃縮咖啡 只會原樣顯示,不會變成項目。

第二,換符號等於開新清單。下面看起來是一份清單,實際上會被解析成兩份:

- 濃縮咖啡
- 可塔多
* 平白咖啡

轉成 HTML 後會是兩個獨立的 <ul>,畫面上就是「可塔多」與「平白咖啡」之間多出一段空隙。這個行為是刻意設計的,因為它是讓兩份相鄰清單不被合併的唯一方法,但實務上多半是複製貼上造成的意外。

插圖:三行前面加了破折號的純文字,逐漸變成整齊縮排的項目符號清單

編號清單與「全部寫 1.」的技巧

編號清單的寫法是:數字、句點、空格,然後是文字:

1. 烤箱預熱到攝氏 180 度
2. 混合乾性材料
3. 拌入融化的奶油

第一個數字之後的數字都會被忽略

這點常讓人吃驚。渲染器只是輸出一個 <ol>,數字交給瀏覽器去數,所以下面這段一樣會渲染成 1、2、3:

1. 烤箱預熱到攝氏 180 度
1. 混合乾性材料
1. 拌入融化的奶油

任何要存進 Git 的文件,都值得養成「全部寫 1.」的習慣,理由有兩個:

  • diff 乾淨。在手動編號的清單中間插入一個步驟,後面每一行都會跟著改,二十行修改裡只藏著一處真正的編輯。
  • 不用管帳。全部寫 1. 的話,增刪一個步驟就只動到一行。

從 1 以外的數字開始

第一個數字被採用,所以清單可以接續前面中斷的編號:

5. 打上版本標籤
6. 發佈更新日誌
7. 對外公告

這段會從 5 開始編號。CommonMark 與 GitHub 風格 Markdown(GFM)有個限制:開頭不是 1 的編號清單無法插斷段落,因此上方一定要留一行空行。你也可以用 1) 取代 1.,而中途更換分隔符號同樣會開啟第二份清單。

巢狀清單:真正有效的縮排

清單壞掉多半壞在巢狀,因為不同渲染器數空格的方式不一樣。現代規則很單純:在 CommonMark(也就是 GitHub 採用的標準)裡,子項目的縮排至少要到達父項目文字開始的那一欄。

- 佔兩個字元寬,所以縮兩格就夠:

- 水果
  - 蘋果
  - 柳橙
    - 臍橙
    - 血橙
- 蔬菜

1. 佔三個字元寬,所以要縮三格:

1. 準備儲存庫
   - Fork 專案
   - Clone 你的 fork
2. 進行修改

小提醒:別去算字元寬度,直接把子項目的符號對齊到父項目文字的第一個字底下。這一招在 - 1. 甚至 10. 底下都成立,也是整份語法參考裡最值得背起來的一條規則。

縮兩格還是四格?

兩格在 GitHub 與所有 CommonMark 解析器上都有效;四格則到哪都有效,包括 Python-Markdown(MkDocs 的核心)與原始的 Markdown.pl,這兩者每一層都要求完整四格。

所以這是看讀者決定的。文件只會出現在 GitHub 上就用兩格;可能被靜態網站產生器編譯,或會貼進陌生的 wiki,就用四格。

渲染器- 底下巢狀1. 底下巢狀Tab 字元
GitHub 與 GitLab(GFM)2 格3 格展開到 4 欄定位點
CommonMark、markdown-it、marked2 格3 格展開到 4 欄定位點
Python-Markdown(MkDocs)4 格4 格轉換成 4 個空格
原始 Markdown.pl4 格4 格視為 4 個空格
到哪都安全4 格4 格不要用 Tab

Tab 鍵的陷阱

對解析器來說,Tab 不等於「四個空格」,而是跳到下一個定位點,跳多遠取決於游標原本在哪一欄。這會帶來三個問題:

  • 同一份清單裡混用 Tab 與空格,層級會不可預測地塌陷或多跳一層。
  • 某些渲染器會把項目裡過寬的縮排當成縮排式程式碼區塊,你的項目變成一段灰色等寬字。
  • 原始檔在編輯器裡看起來完全正常,只有瀏覽器裡是壞的,所以特別難查。

把編輯器設定成「按 Tab 插入空格」,這一整類問題就消失了。

插圖:階梯狀的多層清單,旁邊有一把尺正在丈量每一階的縮排空格數

在清單項目裡放段落、程式碼與引言

清單項目可以容納任何區塊內容:多個段落、圍欄式程式碼區塊、引言區塊。要求永遠一樣:空一行,然後把後續內容縮排到父項目的文字欄位。

第二個段落

- 提交訊息的標題請寫短一點。

  內文可以長一些,而且因為縮排了兩格,
  它仍然屬於同一個項目。

- 下一個項目從這裡接續。

程式碼區塊

要縮排的是圍欄本身,不只是裡面的程式碼。下例縮三格,因為父項目是編號項目:

1. 安裝解析器:

   ```bash
   npm install marked
   ```

2. 在進入點檔案中匯入它。

圍欄縮排不足是這裡的經典錯誤:程式碼區塊脫離清單,清單就此結束,下一個項目的編號從 1 重新開始。如果步驟編號莫名歸零,先檢查歸零處正上方那個圍欄的縮排。更多圍欄行為請見程式碼區塊參考

引言區塊

- 規格書對這點寫得很直白:

  > 清單項目可以包含任何種類的區塊,
  > 包括其他清單。

放進清單的引用內容,除了上面的縮排規則之外,還要遵守引言區塊參考裡的標記規則。表格適用同樣的規則,不過把表格塞進清單項目通常代表這段內容想獨立成一節,什麼時候值得這麼做,表格參考有完整說明。

待辦清單與勾選框

待辦清單是 GFM 的延伸語法:一般的項目符號後面接一組方括號。空的是未勾選,裡面放 x 就是已勾選。

- [ ] 撰寫發佈說明
- [x] 更新版本號
- [ ] 打上版本標籤
  - [x] 簽署標籤
  - [ ] 推送到遠端

空格的位置完全不能省:符號、空格、[、一個空格或一個 x]、空格,然後才是文字。-[ ] 會失敗,因為符號後面沒有空格;- [x]立刻出貨 也會失敗,因為右方括號後面沒有空格。大寫的 [X] 在 GitHub 上可以接受,巢狀規則則與一般項目符號完全相同。

哪些地方的勾選框真的能點

「能渲染」和「能互動」是兩回事,能看到方框的地方,遠多於能勾選的地方:

  • GitHub 的 issue、pull request、discussion 與留言。有編輯權限就能直接點,勾選後系統會改寫底層 Markdown 並更新進度統計。
  • GitHub 或 GitLab 上的 README.md會渲染但唯讀,因為沒有可以寫回去的地方。
  • Obsidian、VS Code 預覽與多數筆記軟體。可以點選,變更會存回你的檔案。
  • 靜態網站產生器。通常渲染成停用狀態的方框。
  • 純 CommonMark 渲染器。根本沒有這個延伸語法,讀者會看到字面上的 [ ]

在不熟悉的平台上使用待辦清單前,值得先看一下 GFM 參考

鬆散與緊密清單:空行為何改變行距

兩份項目完全相同的清單,行距卻可能明顯不同,元凶是一行你沒注意到的空行。緊密(tight)清單的項目之間沒有空行:

- 一
- 二
- 三

它編譯成緊湊的 HTML,文字直接放在每個項目裡:

<ul>
  <li>一</li>
  <li>二</li>
</ul>

鬆散(loose)清單則是內部某處有空行:

- 一

- 二
- 三

這時每個項目都會被包進段落,段落的上下邊距把項目撐開:

<ul>
  <li><p>一</p></li>
  <li><p>二</p></li>
</ul>

鬆散是整份清單的屬性

這一點最常讓人踩雷:

  • 十五個項目裡多出一行空行,十五個項目全部被撐開。
  • 含有兩個段落的項目,也會讓整份清單變鬆散。
  • 所以只要有幾個項目附了說明段落,整份清單看起來就會比你預期的鬆。

兩種形式都沒有對錯:緊密清單適合簡短好掃視的項目,鬆散清單適合每項一句以上的內容。刻意選一種,並讓空行保持一致就好。

常見錯誤與修正寫法

幾乎所有渲染不出來的清單,都出在這五個錯誤:

  1. 清單前面沒有空行,第一個項目被上一個段落吸收。
  2. 符號後面沒有空格,連字號原樣印出來。
  3. 編號底下的巢狀縮排不足,子項目彈回最上層。
  4. 項目之間插入沒縮排的說明,清單被切斷,後面重新編號。
  5. 同一份清單混用不同符號,默默變成好幾份清單並留下空隙。

修正空行與缺少的空格

GitHub 的解析器允許符號清單直接插斷段落,但 Python-Markdown、Markdown.pl、許多 wiki 與絕大多數較舊的渲染器都不允許;而開頭不是 1 的編號清單,在任何平台都不能插斷段落。錯誤寫法與正確寫法:

購物清單:
- 牛奶
- 雞蛋
購物清單:

- 牛奶
- 雞蛋

少一個空格比較容易看出來,因為錯誤的輸入會原樣顯示,連破折號一起印出來。錯誤寫法與正確寫法:

-牛奶
-雞蛋
- 牛奶
- 雞蛋

修正編號底下的縮排

編號父項目底下縮兩格不夠,子項目會彈回最上層。錯誤寫法,以及改成三格、對齊「準」字底下的正確寫法:

1. 準備儲存庫
  - Fork 專案
  - Clone 你的 fork
1. 準備儲存庫
   - Fork 專案
   - Clone 你的 fork

修正把清單切成兩半的說明

沒有縮排的段落會終止清單,後面的項目另起一份新清單,並依它自己的第一個數字重新編號。錯誤寫法,以及把說明縮排、讓它留在第 2 項裡面的正確寫法:

1. 第一步
2. 第二步

記得存檔。

1. 第三步
1. 第一步
2. 第二步

   記得存檔。

3. 第三步

清單怎麼都不渲染時的除錯法

把清單貼進編輯器,一項一項刪到它正確渲染為止。最後刪掉的那一項就是元凶,原因幾乎都是一個空格、一行空行或一段縮排。

空行在這個格式裡是有意義的,原因見 Markdown 的設計初衷Markdown 語法參考表把所有清單寫法濃縮在一頁,姊妹頁面連結圖片則涵蓋大家最常塞進清單項目的兩種元素。

相容性資料驗證日期

常見問題

Markdown 清單該用哪一種項目符號?

用連字號 -。三種符號渲染結果完全相同,但連字號是社群慣例、是多數格式化工具統一轉換的目標,讀原始碼時也不會跟 *斜體* 搞混。真正重要的規則只有一條:保持一致,中途換符號會變成兩份清單。

巢狀清單要縮排幾個空格?

把子項目的符號對齊到父項目文字的第一個字底下:- 底下兩格,1. 底下三格,符合 CommonMark 與 GitHub 的規則。若檔案可能由 MkDocs 或較舊的渲染器編譯,每一層都用四格,這在所有平台都有效。千萬不要混用 Tab 與空格。

為什麼我的編號清單中途從 1 重新開始?

因為有東西終止了清單並開啟新的一份。常見元凶是項目之間出現沒有縮排的段落,或程式碼圍欄沒有縮排到項目的文字欄位。把中間插入的內容縮排到與項目文字對齊,清單就會保持完整。

待辦清單的勾選框在 GitHub 以外能用嗎?

只要支援 GitHub 風格 Markdown 的地方都能正確渲染,包括 GitLab、Obsidian 與 VS Code。但能點選的前提是該工具可以把變更寫回檔案,所以 GitHub 的 issue 可以互動,README 則是唯讀。純 CommonMark 渲染器會直接顯示 [ ]

為什麼我的清單項目之間多出很大的空隙?

清單裡某處的空行讓它變成鬆散清單,於是每個項目都被包進段落。鬆散是整份清單的屬性,所以一行多餘的空行會把全部項目撐開。想要緊密就移除所有空行,想要寬鬆就讓空行保持一致。

延伸閱讀

立即使用編輯器

立即使用編輯器