Markdown 标题语法

写 Markdown 文档,标题(headers/headings)是用得最多的元素之一。不管你写 README、技术博客还是项目文档,标题都是组织内容结构的基本手段。这篇文章把 Markdown 标题语法的方方面面讲清楚——不只是"怎么写",还有"为什么这么写"和"哪些地方容易踩坑"。

Markdown 标题的基本写法

Markdown 支持两种标题风格:ATX 风格Setext 风格。ATX 是绝大多数人在用的方式,Setext 则比较少见但仍然有效。

ATX 风格:用 # 号创建标题

ATX 风格就是在行首用 1 到 6 个 # 号来表示标题级别,对应 HTML 的 <h1><h6>

## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

渲染效果就是从小到大六个级别的标题,一级最大最粗,六级最小。

几个需要注意的点:

  • # 号和标题文字之间必须有空格。写成 #标题 在很多渲染器里不会生效,只会被当成普通文字。说实话这是我自己刚开始用 Markdown 时踩过最多的坑——明明写了 #,为什么渲染出来不是标题?就是因为少了那个空格。
  • # 号数量决定标题级别,1 个 # 是一级(h1),6 个 # 是六级(h6)。
  • 你可以在标题文字后面加上任意数量的 # 作为"闭合",但这是可选的,加了也不影响渲染结果:
## 这是一个二级标题 ##
### 后面的 # 号可有可无 ###

Setext 风格:用下划线创建标题

Setext 风格只支持一级和二级标题,写法是在文字下方加等号(=)或破折号(-):

这是一级标题
=============

这是二级标题
-------------

等号表示一级标题,破折号表示二级标题。下划线的数量不限,写一个也行,写满一行也行,效果一样。

Setext 风格在纯文本里可读性很好——看起来就像传统文档里用下划线标注标题的效果。不过在大多数现代 Markdown 教程和工具中,ATX 风格更常见。我的建议是:如果你只是写文档,统一用 ATX 风格就好,简单不容易搞混。Setext 知道就行,遇到别人的文档能看懂。

两种风格对比

对比项ATX 风格Setext 风格
支持级别h1 到 h6仅 h1 和 h2
语法# 号前缀=- 下划线
可读性源码中一眼看出级别纯文本中更像传统标题
流行度最主流较少使用
编辑便利性增删 # 即可改级别需要增删整行下划线

Markdown 标题级别该怎么用

了解了语法,更重要的问题是:六级标题该怎么用才合理?这涉及到文档结构、SEO 和无障碍访问。

标题级别的语义

标题级别不只是"字号大小",它代表的是文档的层级结构。在 HTML 中,<h1><h6> 构成了页面的大纲,搜索引擎和屏幕阅读器都依赖这个结构来理解内容。

一个好的标题结构应该是:

# 文档标题(h1)
## 第一部分(h2)
### 第一部分的某个子话题(h3)
### 第一部分的另一个子话题(h3)
## 第二部分(h2)
### 第二部分的子话题(h3)

而不应该跳级,比如 h1 直接跳到 h3:

# 文档标题(h1)
### 直接跳到三级标题?❌

虽然语法上不会报错,但跳级会让文档结构混乱,对 SEO 和无障碍访问都不友好。

实际使用建议

  • 一个文档通常只有一个 h1。它就是文档的主标题,相当于书的书名。
  • h2 用来划分大章节,相当于书的章。
  • h3 用来划分小节,相当于章下面的节。
  • h4 到 h6 按需使用,大多数文档用不到那么深的层级。

有一次我帮一个项目整理文档,发现他们直接从 h1 跳到了 h4——因为"觉得 h4 的字号大小刚好合适"。这其实是搞混了标题的语义用途和视觉效果。标题级别反映的是内容结构,字号应该通过 CSS 来控制。

标题的锚点与页内跳转

在很多 Markdown 渲染环境中,标题会自动生成锚点(anchor),你可以用链接直接跳转到某个标题位置。

GitHub 和大多数平台的默认行为

在 GitHub、GitLab 等平台上,标题会自动生成一个 ID,规则是:将标题文字转为小写、去掉特殊字符、空格变成连字符。比如:

## Markdown 标题语法

自动生成的锚点是 #markdown-标题语法。在 GitHub 上,中文标题的锚点处理方式可能和纯英文不太一样,如果需要精确跳转,最好在浏览器中检查一下实际的锚点值。

自定义标题 ID

有些 Markdown 扩展语法支持自定义标题 ID,比如 Pandoc 和 PHP Markdown Extra:

## 我的标题 {#custom-id}

这样你就可以用 [跳转到我的标题](#custom-id) 来创建页内链接了。

不同渲染器的兼容性差异

Markdown 最大的"坑"之一就是不同渲染器对同一语法的处理可能不一样。标题语法虽然相对简单,但也有差异。

空格问题

# 后面加空格这件事,不同渲染器的宽容度不同:

渲染器#标题(无空格)# 标题(有空格)
CommonMark❌ 不识别✅ 正常渲染
GFM(GitHub)❌ 不识别✅ 正常渲染
旧版 Markdown.pl部分识别✅ 正常渲染
markdown-it❌ 不识别✅ 正常渲染

结论很简单:永远加空格,不用纠结。

标题前后的空行

在大多数渲染器中,标题前后不需要空行就能正确识别。但在一些实现中(比如 Flexmark 解析器),标题前面紧挨着代码块、列表或引用时,可能会被误解析。稳妥的做法是标题前后各留一个空行。

Setext 风格的支持度

虽然 Setext 是原始 Markdown 规范的一部分,但有些轻量级 Markdown 解析器不支持它。如果你确定目标平台支持(比如 GitHub、GitLab、CommonMark 兼容的渲染器),用 Setext 没问题。如果不确定,还是用 ATX。

常见问题

Markdown 标题最多有几级?

六级,对应 ######(6 个 # 号加空格)。HTML 规范中 <h1><h6> 也只有六个级别。实际写作中,大多数文档用到 h3 或 h4 就足够了。

为什么我的 # 标题没有渲染?

最常见的原因是 # 后面没有加空格。确保写成 # 标题 而不是 #标题。另一个可能的原因是 # 前面有缩进空格——标题的 # 必须在行首(前面可以有最多三个空格,但最好不要有)。

ATX 和 Setext 哪个更好?

ATX 更实用——它支持六个级别、编辑方便(增删 # 就能改级别)、也更主流。Setext 的优势是在纯文本环境下可读性好,但只支持两级标题。除非你有特殊偏好,建议统一用 ATX。

标题可以用粗体或斜体吗?

可以。标题文字中可以包含行内格式:

## **重点**章节
### 这个功能 *已经废弃*

不过从写作习惯来说,标题本身已经是强调元素了,加粗体有些多此一举,按需使用。

参考来源