Markdown 段落详解:空行、换行与多平台兼容指南
Markdown 段落是什么?比你想的简单
Markdown 里的段落(paragraph)可能是整个语法中最"不像语法"的部分——你不需要任何特殊标记,直接写文字就行。段落之间的分隔靠的是空行,也就是说,只要两段文字之间有一个完全空白的行,它们就会被渲染成两个独立的段落。
说白了,Markdown 段落就是一行或多行连续的文本,段落之间用一个或多个空行隔开。这一规则从 John Gruber 在 2004 年设计 Markdown 的时候就定下来了,到现在也没变过。
渲染的时候,每个段落会被包在 <p> 标签里。所以你在 Markdown 里写:
这是第一段。可以写很多内容,
甚至跨行也没关系。
这是第二段。中间有个空行。渲染出来的 HTML 是:
<p>这是第一段。可以写很多内容,
甚至跨行也没关系。</p>
<p>这是第二段。中间有个空行。</p>这里有个初学者经常忽略的点:段落内连续的几行文字会被合并成一行。也就是说,你在编辑器里敲的回车,在不加任何处理的情况下,渲染出来不会换行——多行会变成一行。
段落创建:空行就是一切
创建段落的方法只有一个:在两段文字之间留一个空行。
第一个段落的内容。
第二个段落的内容。就这么简单。没有标签、没有标记、没有缩进。空行就是段落分隔符。
有几个细节值得注意:
- 空行的定义:一个完全空白的行,或者只包含空格和制表符的行,都算空行。所以即使你不小心在空行上多打了一个空格,它依然能正常分隔段落
- 多个空行 = 一个空行:不管你连续留了几个空行,渲染结果都一样——就是两个段落之间有一段间距。Markdown 不会因为你留了三个空行就让间距变成三倍
- 段落不要缩进:这跟传统中文写作习惯不一样。Markdown 段落开头不需要缩进,也不应该缩进——前面加空格或 Tab 可能会导致内容被解析成代码块(4 个空格 = 代码块),或者产生意想不到的缩进效果
说实话,我刚开始用 Markdown 的时候也犯过这个错——习惯性地在段落开头加两个全角空格,结果在 GitHub 上一看,全变成了奇怪的缩进。后来才明白 Markdown 的设计哲学就是靠空行来分段,不靠缩进。
段落内换行:三种方法
段落之间的分隔用空行,但如果我想在同一段落内换行呢?比如写一首诗,或者排版一个地址。这里有三种常用方法:
方法一:行尾双空格(最经典)
在要换行的位置,先打两个空格,再按回车。
第一行··
第二行(上面用 ·· 表示两个空格,实际写的时候就是普通空格)
这两个空格会被渲染成 <br> 标签,实现段落内换行。这个方法来自 Markdown 的原始设计,所有主流解析器都支持。
但这里有个坑:行尾空格在很多编辑器里是看不见的,而且有些编辑器会自动帮你删掉行尾空格。VS Code 默认就会这样做。如果你发现行尾双空格不生效,先检查一下编辑器设置里有没有"去除行尾空格"的选项。
方法二:行尾反斜杠(更直观)
在行尾加一个反斜杠 \ 再回车:
第一行\
第二行这个方法的好处是反斜杠肉眼可见,不用担心被编辑器偷偷删掉。它是 CommonMark 规范支持的标准写法,GitHub、GitLab、Obsidian 都支持。
不过不是所有解析器都认这个。比如一些老版本的 Markdown 解析器可能不支持行尾反斜杠换行。如果你需要兼容一些不太常见的平台,先测试一下。
方法三:HTML <br> 标签(最通用)
直接用 HTML 的换行标签:
第一行<br>
第二行只要你的 Markdown 解析器允许内联 HTML(绝大多数都允许),这个方法就能用。它的好处是语义明确,不存在兼容性问题。缺点是... 它不算是 Markdown 语法,而是混入了 HTML。
实际使用中,我个人的习惯是:在 GitHub 和大多数平台上用反斜杠(可见、可靠),在需要最大兼容性的时候用 <br>。行尾双空格虽然经典,但因为不可见,实在容易出问题。
不同平台的段落行为差异
这可能是最容易让人困惑的部分——不同平台对段落和换行的处理方式不完全一样。我整理了一个对比表:
| 平台 | 段落分隔 | 段落内换行 | 备注 |
|---|---|---|---|
| GitHub (.md 文件) | 空行 | 行尾空格 / \ / <br> | 标准 GFM 行为 |
| GitHub Issues/PR | 空行 | 直接回车即换行 | 和 .md 文件行为不同! |
| Typora | 空行 | 直接回车即换行(所见即所得模式) | 跟标准 Markdown 有差异 |
| Obsidian | 空行 | 行尾空格 / \ / <br> | 严格模式需手动换行 |
| VS Code 预览 | 空行 | 行尾空格 / \ / <br> | 取决于预览插件 |
| GitLab | 空行 | 行尾空格 / \ / <br> | 标准 GFM 行为 |
重点说一下 GitHub Issues/PR 和 .md 文件的区别。在 GitHub 的 Issues、Pull Request、Discussion 这些评论区域里,你直接按回车就能换行——这跟标准的 Markdown 行为不一样。但在仓库里的 .md 文件中,你必须要用行尾空格或反斜杠才能换行。这个差异一开始挺让人迷惑的。
Typora 的情况也类似。Typora 在所见即所得模式下,回车就直接换行了,因为它的编辑器帮你处理了换行逻辑。但当你把同一个文件放到 GitHub 或其他平台上时,那些单独的回车可能就不会换行了。
段落和其他元素的交互
Markdown 里的段落不是孤立存在的,它和很多其他元素有交互关系,了解这些能帮你避免一些莫名其妙的问题。
段落和列表
列表项里可以包含段落,但需要缩进 4 个空格或 1 个 Tab:
- 第一个列表项
这是列表项内的第二段。注意前面有 4 个空格。
- 第二个列表项如果不缩进,那个"第二段"会被当成普通段落,脱离列表。
段落和引用块
引用块里的段落和外面一样,用空行分隔:
> 引用块里的第一段。
>
> 引用块里的第二段。注意空行上也要加 `>`。注意空行上的 > ——不加的话,引用块会被打断成两个独立的引用。
段落和代码块
如果你在段落文字前面加了 4 个空格或者 1 个 Tab,它就不再是段落了——它会被解析成一个代码块。这是新手特别容易踩的坑:
这是普通段落。
这变成了代码块,因为前面有 4 个空格。段落和标题
标题前后建议留空行。虽然有些解析器不要求,但养成这个习惯能避免很多兼容性问题:
## 这是一个标题
标题下面的段落内容。常见问题与排查
为什么我的段落没有换行?
最常见的两个原因:
- 没有留空行——段落之间必须有一个完全空白的行
- 空行上有不可见的字符——可能是空格或 Tab,虽然这些在规范中算空行,但某些解析器可能处理不一致
为什么多行文字渲染成了一行?
这是标准 Markdown 行为——段落内的连续行会被合并成一行。如果你想在段落内换行,用前面说的三种方法之一。
有一次我在 Obsidian 里写一篇笔记,连续写了好几行都没换行,以为是 Obsidian 的 bug。后来才明白这就是 Markdown 的设计——行内的换行符被忽略了,除非你用行尾空格或反斜杠明确告诉它"这里要换行"。
为什么我的段落变成了代码块?
段落前面有 4 个或以上空格,或者 1 个或以上 Tab。检查一下段落开头是不是不小心多打了空格。
连续多个空行为什么没效果?
Markdown 规范里,多个连续空行等价于一个空行。如果你确实需要更大的间距,要用 HTML 的方式处理(比如多个 <br> 或者 CSS),不能靠堆空行。
行尾双空格不生效怎么办?
先检查编辑器是不是自动删除了行尾空格。VS Code、Sublime Text 等编辑器默认会这么做。你可以在编辑器设置中关闭这个功能,或者改用反斜杠和 <br> 这两种替代方案。
Markdown 段落的完整参考表
| 操作 | 语法 | 说明 |
|---|---|---|
| 创建段落 | 段落之间留空行 | 一个或多个空行效果相同 |
| 段落内换行 | 行末加两个空格再回车 | 最经典的方法,所有解析器支持 |
| 段落内换行 | 行末加 \ 再回车 | CommonMark 支持,更直观 |
| 段落内换行 | 使用 <br> 标签 | HTML 方式,兼容性最好 |
| 多段落列表项 | 列表项内缩进 4 空格 | 第二段起的段落需缩进 |
| 引用块内多段落 | 空行上也加 > | 保持引用连续性 |