Markdown 分割线(水平线)语法教程
写长文档的时候,在两个主题之间插一条分割线(horizontal rule),能让内容结构更清晰。Markdown 的分割线语法特别简单——三个字符就能搞定,但有几个小坑值得注意。
Markdown 分割线的基本语法
在 Markdown 里,分割线有三种写法,效果完全一样:
---
***
___三种写法渲染出来的结果都是一条横贯页面宽度的水平线,对应的 HTML 标签是 <hr>。
根据 CommonMark 规范,这三种写法也叫"主题分隔"(thematic break)。你用哪种都行,关键是至少要写三个字符,而且必须单独占一行。
超过三个也行,比如 ----- 或 *******,效果不变。
三个短横线(最常用)
第一部分内容。
---
第二部分内容。这是用得最多的写法。GitHub 上大约 92% 的 Markdown 文件都用 --- 来做分割线。
三个星号
第一部分内容。
***
第二部分内容。星号写法有个好处:不会和标题语法冲突(后面会详细说)。如果你特别在意这一点,可以用星号代替短横线。星号之间加空格也行,* * * 是合法写法。
三个下划线
第一部分内容。
___
第二部分内容。下划线是最少人用的写法,但同样有效,所有主流 Markdown 解析器都支持。
语法规则详解
虽然写法简单,但有几条规则必须遵守,不然分割线可能显示不出来,甚至变成别的东西。
必须单独占一行
分割线所在的那一行只能有分割线字符(前后可以有空格),不能有其他文字:
<!-- 正确 -->
一些文字
---
更多文字
<!-- 错误:同一行有其他文字 -->
--- 这不是分割线前后要留空行
这一点特别重要。--- 在某些情况下会被解析器当作二级标题的下划线(Setext 风格标题),而不是分割线:
<!-- 这会变成 H2 标题,不是分割线! -->
一些文字
---
<!-- 这才是分割线 -->
一些文字
---
更多文字我之前在写一个项目的 CHANGELOG 时就踩过这个坑——版本号下面紧跟着 ---,结果版本号变成了大标题,分割线反倒没了。解决办法很简单:在 --- 上面加一个空行。
不能混用不同字符
每一行的分割线只能用同一种字符,混着写是不行的:
<!-- 错误:混用了短横线和星号 -->
--*
-*-
<!-- 正确:只用一种字符 -->
---至少三个字符
两个字符不够,必须三个或以上:
<!-- 错误:只有两个 -->
--
<!-- 正确:三个或更多 -->
---
-----不同平台的渲染差异
虽然所有主流平台都支持这三种写法,但渲染出来的样式略有区别:
| 平台 | 支持情况 | 渲染样式 |
|---|---|---|
| GitHub | 支持 | 细灰色线,约 1px,上下有 24px 间距 |
| GitLab | 支持 | 细灰色线 |
| 支持 | 细线 | |
| Stack Overflow | 支持 | 细线 |
| Notion | 支持 | 可用 --- 或 /divider 命令,转为原生分割线块 |
| Obsidian | 支持 | 跟随主题配色的细线 |
| VS Code 预览 | 支持 | 浏览器默认 <hr> 样式 |
| Typora | 支持 | 细线,可通过 CSS 自定义 |
| Discord | 不支持 | 无分割线功能 |
| Slack | 不支持 | 无分割线功能 |
用 HTML <hr> 标签作为替代
如果 Markdown 的分割线语法不生效(比如某些特殊环境),可以直接用 HTML 的 <hr> 标签:
一些文字
<hr>
更多文字大多数支持 Markdown 的平台也支持内联 HTML,所以 <hr> 基本都能用。效果和 Markdown 语法一样。
自定义分割线样式
Markdown 本身不支持样式定制,但如果你用的平台允许 HTML 和 CSS,可以通过几种方式来美化分割线。
行内样式
直接在 <hr> 标签上加 style 属性:
<hr style="border: 2px solid #333; width: 60%; margin: 2em auto;">这会渲染出一条深灰色、宽度为页面 60%、居中的分割线。GitHub 和大部分静态站点生成器都支持这种写法。但 Obsidian 的实时预览和一些会过滤 HTML 的编辑器可能不支持。
全局 CSS
如果你有自己的站点或博客,最好在 CSS 里统一定义分割线样式,而不是每个地方都写行内样式:
hr {
border: none;
border-top: 2px dashed #ccc;
margin: 2em 0;
}这样 Markdown 里所有的 --- 都会自动应用这个样式。
markdown-it 自定义渲染
如果你用 Eleventy、VuePress 这类基于 markdown-it 的静态站点生成器,可以通过覆写渲染规则来完全自定义 <hr> 的输出。
const markdownIt = require("markdown-it")
const mdSetup = markdownIt()
mdSetup.renderer.rules.hr = (tokens, idx, options, env, self) => {
return '<hr class="custom-divider" />'
}这样所有 Markdown 里的分割线都会渲染成带 custom-divider 类名的 <hr> 标签,你可以用 CSS 随意美化它。
分割线的实际使用场景
分割线用对了地方能让文档更有条理,用多了反而显得乱。以下是一些适合用分割线的场景:
项目介绍和功能描述...
---
## 更新日志
### v2.0.0
- 新增了用户管理功能
- 修复了登录超时问题
---
### v1.0.0
- 初始版本发布- README 的章节之间:把安装说明和使用说明隔开
- 更新日志的版本之间:每个版本条目前后用分割线
- 正文和附录/脚注之间:区分主体内容和补充信息
- 主题切换的地方:两个完全不相关的话题之间
对了,如果每两三个段落就插一条分割线,那说明你可能应该用标题来分节,而不是分割线。分割线适合用在标题不太合适、但又需要一个明显视觉间隔的地方。
三种写法该选哪个?
说实话,选哪个都行,一致性比具体选哪个更重要。我的建议是:
| 写法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
--- | 最常见,最直观 | 不加空行会和标题冲突 | 日常使用(记得加空行就行) |
*** | 不会和标题冲突 | 较少人用 | 担心标题冲突的团队规范 |
___ | 同上 | 更少人用 | 个人偏好 |
我个人一直用 ---,只要记住上面加个空行就没事。如果你在给团队写编码规范,*** 是最安全的选择,因为它完全消除了和标题混淆的可能性。
常见问题
为什么我的 --- 变成了标题?
因为 --- 紧跟在文字下面时,会被解析为 Setext 风格的二级标题。在上面加一个空行就能解决。
两个短横线 -- 能做分割线吗?
不能。至少需要三个。两个短横线在某些解析器里是删除线或破折号,和分割线无关。
分割线能加颜色或改粗细吗?
纯 Markdown 不行。但如果你用的平台支持 HTML,可以用带样式的 <hr> 标签实现,或者在站点的 CSS 里统一修改。
分割线和空行有什么区别?
空行只是增加段落间距,分割线会渲染出一条可见的横线。如果你只需要段落间距,用空行就够了,不需要分割线。
Discord 和 Slack 为什么不支持分割线?
这两个平台的 Markdown 支持是有限的子集,它们没有实现 thematic break 语法。在 Discord 和 Slack 里,你只能用 emoji(比如 ————— 或 - - -)来模拟分割线的效果。