1. Markdown 基础语法:所有渲染器都支持的部分
Markdown 由 John Gruber 于 2004 年创建,Aaron Swartz 参与了语法设计;它公开声明的设计目标解释了本节每个语法为什么长成这样:原始文本必须保持「写出来什么样,读起来就什么样」,见 Daring Fireball 的原始语法说明。这些标记借自纯文本电子邮件的惯例——星号表强调、> 表引用——为的是让人类可直接阅读的文本干净地转换成 HTML,而不需要任何格式工具栏。这个目标同样解释了核心语言的克制:语法长得像标点,结构靠空行与缩进推断,任何太模糊、无法可靠解析的东西都被直接排除在外。如果你对这门格式还很陌生,我们的 Markdown 定义与历史详解讲清了它的来龙去脉。本节语法在 GitHub、Obsidian、Notion 以及所有主流引擎里渲染行为完全一致——值得进肌肉记忆,而不是躺进书签;想确认渲染效果,在线查看器现贴现看。
1.1 标题
标题是以一到六个 # 开头、后跟一个空格和标题文本的行。
# 文档标题 (H1)
## 小节标题 (H2)
### 子小节标题 (H3)
#### 第四级 (很少是好主意)
一个文档只用一个 #,小节用 ##,子小节用 ###;更深的层级虽然存在,但通常说明内容该拆页了。跳级——H1 后面直接 H3——照样能渲染,却会给屏幕阅读器和目录生成器留下一份断裂的大纲,因为标题是文档的真实结构,不是装饰。还有一个安静的错误模式:#标题 少了井号后的那个空格时,会被当成字面文本渲染,而不是标题。
1.2 强调与行内代码
**bold** 渲染为加粗
*italic* 渲染为斜体
***bold italic*** 渲染为粗斜体
`inline code` 渲染为等宽字体
强调请优先用星号而不是下划线:snake_case_name 不会斜体,因为引擎把词内下划线当作字面字符;而 snake*case*name 会生效。加粗留给扫读时绝不能错过的少数关键词——全都加粗等于全都没加粗。行内代码用单个反引号包裹,标记一切需要按字面输入的东西——命令、文件名、参数——它那层浅色背景使它成为段落里最强的视觉锚点,所以要花在真正的代码上,而不是变相的强调。
1.3 链接与图片
[锚文本](https://example.com/docs)

[引用式链接][docs],定义放在文件中的其他位置:
[docs]: https://example.com/docs
链接与图片共享同一套语法,靠开头的 ! 区分。替代文本是屏幕阅读器朗读的内容,也是图片加载失败时显示的内容,所以要描述图片展示了什么,而不是重复文件名。引用式链接把 URL 集中放在文件末尾,存在的原因和 Markdown 的一切一样:让段落的原始形态保持可读。
1.4 引用与水平线
> 引用的第一行。
> 第二行仍在同一段引用里。
> 空行之后开始另一段独立引用。
---
引用块内部可以放任何 Markdown,所以 > **注意:** … 和引用套引用(> > …)都能渲染。水平线有一个坑:上方需要空行,因为紧跟在文字后面的 --- 会按 setext 规则把那段文字变成 H2 标题——这是「凭空多出一个节标题」最安静的方式。
1.5 列表与缩进规则
- 无序列表项
- 另一个列表项
- 嵌套项(在 "-" 父项下缩进两个空格)
1. 有序列表项
2. 第二项
- 嵌套在 "2." 下的子弹(三个空格)
无序列表的 -、*、+ 效果相同可以任选;有序列表会自动重新编号——渲染序号跟随列表本身,而不是你输入的数字。嵌套正是渲染开始出问题的地方,因为解析器只有在一行缩进到与父项文本对齐时才把它归入父项:在 - 父项下两个空格就够,在 2. 父项下至少需要三个。统一缩进四个空格在任何标记下都成立,所以风格指南把整个话题压缩成一句「缩进四格」——第 3.1 节会展示这个对齐一旦失手会发生什么。
2. GFM 扩展:GitHub 定义的方言
2004 年的原始规范在边界情况上出了名地含糊,各实现因此渐渐分道扬镳,直到 CommonMark 项目为核心语法钉出一份无歧义的规范,而 GitHub Flavored Markdown 在文档中被明确为这份核心的严格超集,见 GitHub 的 GFM 规范。下面五个扩展扩散到了 GitHub 之外——它托管着全世界的 README:GitLab、Obsidian、Pandoc、VS Code 和多数文档工具如今都遵循同一方言;当 AI agent 被要求输出结构化文档时,产出的也多半是它——什么时候这很重要,见我们对 HTML vs Markdown(AI 输出格式)的对比。Notion 是个显眼的例外:导入时它理解大部分 GFM,然后把文档规范化成自己的块模型——所以把这五项当作核心之上加学的第二层。
2.1 表格与列对齐
| 特性 | 核心 Markdown | GFM |
|------------|:--------------|----:|
| 表格 | 否 | 是 |
| 任务清单 | 否 | 是 |
一张 GFM 表格 = 表头行 + 必需的横线分隔行 + 数据行——漏掉分隔行,整块内容会塌成一串字面竖线,这是「表格坏了」报告里最常见的原因,完整的表格语法指南也从这里讲起。冒号是可选的,控制整列对齐::--- 左对齐、:---: 居中、---: 右对齐。每个单元格只装得下一行内容;不存在「单元格里写段落」的语法,所以表格适合紧凑的、可对比的事实,而每个单元格都需要成段文字的内容应该改用嵌套列表或独立小节。单元格里的字面竖线必须转义——第 3.2 节专门讲这个失败模式。
2.2 任务清单
- [ ] 写完大纲
- [x] 写完可复制的示例
- [ ] 验证每个代码块都能渲染
任务清单是文本以 [ ] 或 [x] 开头的列表项,渲染成复选框——在 GitHub 的 issue 和 pull request 里它真的可以点选,点击还会写回源文本,见 GitHub 的写作文档。这种「读写诚实」使它成为 README 贡献步骤、迁移清单、发布计划的标准写法:即使在复选框不渲染的地方,原始文本依然准确。其他引擎的降级也是优雅的而非崩坏——Obsidian 渲染为真实复选框,Notion 在导入时把该语法转换成自己的 to-do 块。
2.3 围栏代码块与语言标注
```python
def greet(name):
return f"Hello, {name}!"
```
三个反引号开合一个围栏代码块,开头围栏后的那个词——python、bash、json 等等——标注语言以获得语法高亮。标注是可选的,但很少应该省略:没有它就失去高亮,而且一些流水线会读取标注来决定是否对该代码块做 lint、测试或执行。围栏存在的原因,是旧的代码块写法——每行缩进四个空格——对长代码块太繁琐,还和列表缩进互相干扰;围栏内的空白按原样保留。要显示字面的三反引号围栏——本文通篇在这么做——就用四反引号围栏把它包起来。
2.4 删除线与自动链接
~~这个估算是错的~~ 但方法本身成立。
裸 URL 自动成链:https://example.com
显式自动链接:<https://example.com>
删除线——两个波浪号包住文本——标记一处更正同时保留原文,变更日志和勘误表靠它保住上下文,而不是悄悄改写历史。自动链接是 GFM 对「就不能直接贴个 URL 吗」的回答:裸的 https:// 或 www. 地址无需任何括号语法就变成链接,而尖括号形式 <https://…> 把整个 URL 钉死为链接目标。两者都是方言特性而非核心 Markdown:严格的原始规范渲染器会把波浪号原样打印出来。
3. 高频易错坑:渲染悄悄坏掉的四种情形
渲染器几乎从不大声报错。坏掉的列表变成连成一片的段落,坏掉的表格变成一面竖线墙,文档照样「能用」——只是不再表达你的本意。下面四种情形造成了其中大部分破坏,而且全部同根同源:解析器如何读空白与分隔字符,与任何冷僻语法无关。
3.1 嵌套列表:逃逸或变成代码
1. 构建项目
2. 跑测试
- 单元测试
3. 部署
在 2. 这个列表项下,文本从第四列开始,因此嵌套子弹至少要缩进三个空格;上面那个两格缩进的子弹根本不属于第二项——它把有序列表撕成了几段。缩进过多的失败方式则相反:一行一旦超过父项文本列四个及以上空格,解析器就把它当成缩进代码块——列表项后面跟出一个灰框。药方无聊但有效:选定统一缩进,永远不要混用制表符与空格,嵌套进有序项时,数一数它的文本从第几列开始。
3.2 竖线、空行,与「表格变正文」
| 工具 | 单元格里的字面竖线 |
|------|--------------------|
| GFM | 需要转义:a \| b |
两个习惯能预防几乎所有坏表格。第一,单元格里任何字面 | 都写成 \|;未转义的竖线会悄悄切分单元格,一旦该行的列数与表头对不上,引擎就把整张表格降级成纯文本。第二,表格上方留一个空行——紧跟在段落后面输入的表格会被那个段落连同竖线一起吞掉。空行规则是通用的:空行就是 Markdown 分隔块的方式,所以任何「莫名其妙和上文粘在一起」的表格、列表或代码块,缺的都是一个空行。
3.3 行内代码里包含反引号
`` `code` `` 渲染为:`code`
行内代码用一段连续反引号定界,内部的反引号串长度必须与定界符不同——标准写法是把外层反引号加倍、两侧各垫一个空格,如上所示。这条长度规则可以推而广之:要在行内写到三反引号围栏,就用四个或更多反引号做定界符。在你开始写代码文档、或写「关于 Markdown 的文章」之前,这一直是个冷门需求——到了那一天就不再冷门。
3.4 同一种语言,多种方言
GitHub、Obsidian、Notion 都「说 Markdown」,而这三家迟早都会给你惊喜。GitHub 严格按自家规范渲染,并把原始 HTML 过滤到一份白名单;Obsidian 在近似 GFM 的底座上加了非标准扩展,比如 wiki 链接([[笔记]])和原生数学公式;Notion 在你打字时实时解释 Markdown,并把导入的文档转换成自己的块模型,方言特性不一定能在旅程中幸存(截至 2026 年 9 月)。Markdown Guide 的方言概览追踪了各引擎对各扩展的支持情况,发布任何超出「核心 + GFM」的内容前值得扫一眼。通用防线是行为性的:在文档真正要居住的引擎里测试它——这和把 HTML 转换为 Markdown 是同一种纪律,产出的内容要对着目标工具验证,而不是对着来源。
4. 把速查表练成肌肉记忆
速查表不是给第一次查询用的,而是给第三次——那时你已经懒得再查了。毕业的方法是带即时反馈的练习,而本页每个示例都是纯文本,所以这个循环便宜得很。Floatboat 的 Markdown 工具页正是围绕这个循环构建的——把本文任意片段投进去,看表格或嵌套列表渲染出来,然后故意弄坏它(删掉分隔行、把子列表缩进错位),看会发生什么变化。一分钟刻意的破坏,胜过一小时的重读。
第二个习惯,是让你的真实工作流经这种格式,直到语法不再是有趣的部分。用 Markdown 写的笔记、README、会议纪要和 agent 提示词会滚成真正的文档;而当文档需要离开编辑器——交给客户的 PDF、评审里干净的 diff——那是转换问题,不是重写问题,我们的 Markdown 转 PDF 指南讲的就是不装 LaTeX 工具链的做法。核心保持小巧:十几个构造就覆盖了大多数人写的几乎全部文档——把它们练到不假思索,让这一页保管长尾。
5. 结语
语法本身很小——这一页已经是大半。剩下的复杂度是方言性的:知道表格和任务清单来自 GFM,知道缩进规则存在是因为解析器按列把行归属给列表项,知道目标引擎永远拥有最终解释权。所以,请按本文示例本来的用法来用这份速查表——贴进去、故意弄坏、再贴一次,直到修复变成条件反射。熟练的 Markdown 作者不是背下了更多语法的人,而是完全不再想语法的人:上千次「贴进去看结果」的循环,已经把渲染器会做什么教给了他们的手。
https://floatboat.ai/zh/blog/markdown-cheat-sheet
