嵌套列表
嵌套列表让一份清单能表达层级:功能点下面挂子功能,步骤里面再分步骤,配置项下面列具体字段。但 Markdown 里没有专门的「嵌套」语法——层级完全靠缩进表达,于是「缩进多少」就成了一个必须精确回答的问题。坊间流传着「二级列表必须缩进四个空格」的说法,这其实是把某一种写法当成了规范。这一页要给出真正起作用的规则,并说明为什么两格和四格都能work。
子项只要缩进到父项内容起始的那一列或更右,就会被认作它的子项:
- 一级
- 二级
- 三级
- 另一项
<ul>
<li>一级
<ul>
<li>二级
<ul>
<li>三级</li>
</ul>
</li>
</ul>
</li>
<li>另一项</li>
</ul>
真正的规则:内容起始列
缩进多少合适,取决于父项的内容起始列,也就是标记符号本身占掉的宽度:
| 父项标记 | 标记占宽 | 子项应缩进 |
|---|---|---|
- 加空格 | 2 列 | 2 列 |
* 加空格 | 2 列 | 2 列 |
+ 加空格 | 2 列 | 2 列 |
1. 加空格 | 3 列 | 3 列 |
10. 加空格 | 4 列 | 4 列 |
所以短横线列表缩进两格就对,有序列表的子项要缩进三格。而缩进四格在短横线列表里同样有效——因为四格仍然落在「父项内容列到内容列加四格」这个区间内,解析器会把它当成子列表而不是代码块。真正会变的是再往右一格:短横线列表的子项缩进到六格时,就越过代码块的门槛了。
换句话说,两格和四格都行,关键是别超过上限。
一致性比具体数值更重要
同一个层级的兄弟项,缩进必须落在同一档里。缩进不一致时,解析器可能把它们拆成两个平级的子列表,视觉上像是多了一层:
- 一级
- 四格的二级
- 两格的二级
<ul>
<li>一级
<ul>
<li>四格的二级</li>
<li>两格的二级</li>
</ul>
</li>
</ul>
上面这个例子因为两格和四格都还在同一个区间内,所以侥幸被合成一个子列表。但只要有一项越过了门槛,它就会被甩出去,变成代码块或者另起一个列表。
| 写法 | 实际渲染 | 原因 |
|---|---|---|
| 子项缩进两格 | 正常嵌套 | 短横线的内容起始列是第 3 列 |
| 子项缩进四格 | 正常嵌套 | 仍在子列表区间内 |
| 子项缩进六格 | 变成代码块 | 超过内容起始列四格 |
| 兄弟项缩进不一致 | 可能被拆成两个列表 | 同一层级要落在同一档 |
| 子项换了符号 | 另起一个子列表 | 换符号等于另起一个列表 |
不要用制表符和空格混着缩进。 规范允许一个制表符当作四格用,但不同编辑器对制表符宽度的设置不一致——同样一个缩进,在你的编辑器里是四格,在别人那里可能显示成八格。写文档时统一用空格,最省心。
把下面这段内容改写成 Markdown 要求:三个顶层要点用一个无序列表表示;「安装依赖」下面挂两个子项;「配置」下面挂一个有序子列表,子列表的第一个编号必须是 1。整份文档的缩进保持一致。
安装依赖
安装 pnpm
执行 pnpm install
配置
环境变量
列出 NODE_ENV
列出 PORT
发布
解题思路:
嵌套靠缩进表达,缩进量取决于父项的内容起始列。短横线 - 占两列,所以无序列表的子项缩进两个空格;有序列表 1. 占三列,所以它的子项缩进三个空格。整份文档统一用空格,不用制表符。
详细步骤:
- 三个顶层要点各写
-加空格,顶格排列。 - 「安装 pnpm」和「执行 pnpm install」是「安装依赖」的子项,缩进两个空格再写
-,与父项的内容起始列对齐。 - 「环境变量」是「配置」的子项,同样缩进两个空格;但它下面还要再挂一层有序列表。
- 「列出 NODE_ENV」和「列出 PORT」构成一个有序列表,它挂在「环境变量」下面。「环境变量」这一行前面有两个空格,它的内容从第 5 列开始,所以这个有序列表整体要缩进四个空格;列表内部的编号写
1.和2.。 - 检验:渲染后是三个顶层要点,「安装依赖」下有两个子项,「配置」下有一个有序子列表。
最终答案:
- 安装依赖
- 安装 `pnpm`
- 执行 `pnpm install`
- 配置
- 环境变量
1. 列出 `NODE_ENV`
2. 列出 `PORT`
- 发布读完这一页,你应当能说出嵌套靠缩进表达、而缩进量由父项的内容起始列决定,能说清两格和四格为什么都有效、什么情况下会变成代码块,也能在「层级莫名多了一层」时想到是兄弟项缩进不一致。接下来写多层清单时,你会先确定顶层用哪种标记,再按标记占宽统一每一层的缩进,而不是随手敲空格。
