Markdown 列表语法
无序/有序/任务列表语法、嵌套缩进规则、起始序号控制与列表内嵌块级元素的细节。
知识点地图
- 知识类别:列表语法——无序/有序/任务三种列表及其嵌套、内嵌块级元素与边界行为。本篇是列表主题的唯一专篇(原引用篇中的列表章节已归并至此)。
- 解决什么问题:并列信息怎么写;嵌套层级怎么不塌;有序列表的起始序号控制;列表里放代码/引用/段落。
- 什么时候用到:README 的安装步骤(有序)、特性清单(无序)、待办(任务);文档里几乎每三段就有一个列表。
认知导入(Layer 0 生存层) 前置知识:003 段落与换行。 边界说明:列表是”并列信息”的默认表达。本篇的核心难点只有一个——缩进决定层级;其余都是三种列表的排列组合。 强制练习:分别用
-和1.写三行列表;把第二行缩进两个空格,观察它如何变成子项。
1. 无序列表
1.1 语法
-、*、+ 加一个空格开头,三种标记渲染效果完全一致。团队内统一用一种(推荐 -,输入最快且不会被斜体语法干扰):
- 无序列表项 1
- 无序列表项 2
- 无序列表项 3标记后必须有空格:-列表项 不是列表,是普通文本。
1.2 多行内容与续行
列表项内容太长需要换行时,续行缩进到与首行文本对齐(懒延续也允许不缩进,但对齐写法更可靠、更易读):
- 这是一个很长的列表项,
换行后与首行文本对齐,
仍然属于同一个列表项
- 另一个列表项1.3 松散与紧凑
项与项之间加空行会形成”松散列表”,渲染时行距更大(每项包裹在段落里);不加空行则是紧凑列表。两种都合法,同一文档保持一种风格——markdownlint 的 MD032 规则可以帮团队强制统一。
2. 有序列表
2.1 语法
数字 + 英文句号 + 空格 开头:
1. 第一项
2. 第二项
3. 第三项2.2 序号规则:首项决定起始值
这是有序列表最容易被讲错的规则,分两层:
- 第一项的数字决定列表从几开始:写
3. a\n4. b会渲染成从 3 开始的列表(用于在长文档中续接编号); - 后续项的数字不影响显示:全部写
1.也能渲染出递增序号,渲染序号自动连续。
3. 从三开始
4. 自动递增为四
5. 自动递增为五实践建议:源码按真实顺序书写(1. 2. 3.),既保证起始值正确,也让 diff 与阅读友好。
2.3 有序列表也能嵌套
子项缩进到父项内容列(1. 占 3 列,缩进 3 空格):
1. 一级项
1. 二级项
2. 二级项
2. 另一个一级项3. 任务列表
任务列表是 GFM 扩展:在列表项开头加 [ ](未完成)或 [x](已完成,大小写均可):
- [ ] 未完成的待办任务
- [x] 已完成的待办任务
- [ ] 可嵌套的子任务识别条件严格:标记必须是列表项内容的开头、方括号内只能有空格或 x、标记后必须有空格。GitHub/GitLab 上复选框可点击勾选并写回源码。详细语义、交互行为与渲染器差异见 markdown/170-TaskList。
4. 嵌套列表与缩进规则(本篇重点)
4.1 缩进的本质:对齐父项内容列
CommonMark 的判定标准是”子列表缩进到父项内容的起始列”,不是全局固定值:
- 无序父项
- 二级项(缩进 2 空格,对齐"无"字)
- 三级项(再缩进 2 空格)
1. 有序父项
- 二级项(缩进 3 空格,对齐"有"字)
10. 两位数父项
- 二级项(缩进 4 空格)两条硬性边界:
- 缩进不足(少于父项内容列):子项被解析为父项的同级,层级塌掉——这是嵌套列表翻车的第一名;
- 缩进过头(相对内容列达到 4 空格):内容被解析为缩进式代码块,出现奇怪的缩进代码。
因此”嵌套列表必须缩进 4 空格”是一个流传很广的误解:对 - 项它反而逼近代码块阈值,正确做法是最小对齐缩进(无序 2 空格、有序 3 空格)。
4.2 制表符风险
CommonMark 把制表符按”跳到下一个 4 列倍数”展开,理论上一个制表符等价 4 空格;但不同编辑器对 Tab 的显示宽度不同,混用空格与制表符是层级错乱的常见根源。列表缩进只用空格,并在编辑器里开启”Tab 转空格”。
4.3 不同类型混合嵌套
无序与有序可以互相嵌套:
- 无序列表项
1. 内部有序第一步
2. 内部有序第二步
- 无序列表项4.4 层级深度建议
渲染层面没有硬性上限,但三层以上读者就难以追踪归属,超过三层应考虑拆分列表或改用小标题。
5. 列表项内嵌块级元素
列表项可以承载段落、代码块、引用等块级元素,关键是整体缩进到父项内容列。
5.1 嵌入代码块(推荐围栏式)
- 列表项 1
```python
print("Hello, World!")
```
- 列表项 2代码块缩进 2 空格(与 - 项的内容列对齐)即可识别为项内代码块;缩进式代码块则要求相对内容列再加 4 空格,容易出错,优先用围栏式。
5.2 嵌入引用
- 列表项 1
> 这是列表项内的引用
> 可以跨多行
- 列表项 25.3 嵌入链接与图片
行内元素直接写即可:
- [Markdown 指南](https://www.markdownguide.org)
- 本地图片:图片路径建议使用仓库内相对路径而非外部占位图服务(外链图床容易失效)。
5.4 嵌入段落
空行 + 缩进:
- 列表项 1
这是列表项内的一个段落,可以写详细说明。
- 列表项 26. 列表与段落的边界行为
CommonMark 规定:列表可以打断段落(无序列表、以及首项为 1 的有序列表可以直接跟在段落文字后一行开始);首项不是 1 的有序列表不能打断段落。这在”正文后直接写列表”时通常无害,但当你写的是以连字符开头的一行普通文字(如日期 - 2026-01-01 事件)时,可能意外变成列表——必要时用转义 \- 或前置空行处理。
7. 常见问题排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 列表显示为普通文本 | 标记后缺空格 | - 列表项(减号后加空格) |
| 嵌套项与父项同级 | 缩进少于内容列 | 无序 2 空格、有序 3 空格 |
| 子项变成代码块 | 缩进达到内容列 +4 空格 | 减少缩进到对齐即可 |
| 有序列表从 2 或 3 开始 | 首项数字不是 1 | 起始序号由首项数字决定 |
| 任务没有复选框 | 渲染器不支持 GFM 或标记写法错误 | 核对 [ ] 与空格;换 GFM 渲染器 |
| 列表项间距忽大忽小 | 紧凑/松散混用 | 项间统一不加空行 |
| 有序列表项内换行被切成新段落 | 1. 项的续行未缩进 | 续行缩进 3 空格(对齐内容列) |
小结
- 初学者要点:无序用
-、有序用1.,标记后加空格;嵌套缩进”无序 2 空格、有序 3 空格”;列表里放代码块用围栏式并保持缩进。 - 进阶注意:缩进的本质是对齐父项内容列,4 空格是代码块阈值不是列表标准;有序列表的起始值由首项数字决定、后续数字被忽略;任务列表是 GFM 扩展(详见
markdown/170-TaskList);列表可打断段落,首项非 1 的有序列表除外;缩进只用空格不用制表符。
动手实践
练习 1(缩进边界实验):写一个无序嵌套列表,子项分别缩进 1、2、5 空格各试一次,观察 1 空格塌成同级、2 空格正常、5 空格变代码块的三种结果。
提示:判定标准是「对齐父项内容列」(- 为 2),不是固定 4 空格。
练习 2(起始序号续接):写一个 1-5 的有序列表,中间插入一段说明文字,然后用 6. 作为下一项首数字续接列表,验证渲染序号连续。
提示:续接项的首数字决定起始值;后续数字随便写。
练习 3(列表内嵌代码):在列表项内放一段代码(分别用围栏式与缩进式),验证围栏式只需对齐内容列、缩进式要求内容列 +4。
提示:工程结论是永远用围栏式——缩进式的 6 空格要求一碰就碎。
参考实现(先自己动手,再看这里)
<!-- 练习 1 -->
- 父项
- 一空格:塌成同级
- 两空格:正确子项
- 五空格:内容列(2)+4 = 代码块阈值,渲染为代码
<!-- 练习 2 -->
1. 安装依赖
2. 修改配置
> 中间可以插说明文字
6. 启动服务 <!-- 渲染为 3.(首项数字 6 不生效,因为列表未断) -->
<!-- 注意:若列表被空行+非缩进内容真正打断,6. 会从 6 开始——这正是 §2.2 的规则 -->
<!-- 练习 3 -->
- 项目一
```js
console.log("fenced") // 围栏式:缩进 2 格即可-
项目二
plaintextconsole.log("indented") // 缩进式:需 6 格
</details>