脚注
Markdown 脚注语法:标记与定义的配对模型、为什么需要脚注、定义位置无关渲染顺序、多平台兼容性与遮代码自检实践。
1. 脚注概述
1.1 什么是脚注
脚注(Footnote)允许在文档中添加补充说明,读者可以点击上标标记跳转到文末的详细注释。脚注常用于:
- 学术论文中的引用来源
- 技术文档中的补充说明
- 长文中的额外细节,避免打断正文阅读流
为什么需要它:写作时经常要在”正文流畅”与”信息严谨”之间做交换——来源、勘误、边角细节都值得写,但直接插进正文会压断主线。脚注把这笔交易做成了机制:正文只留一个上标,重量全部移到页面底部,愿意深究的读者点一下,赶时间的读者一行都不用看。它是”先给主线、按需展开”的信息分层设计。
1.2 脚注与尾注
| 类型 | 位置 | 适用场景 |
|---|---|---|
| 脚注 | 页面底部 | 学术论文、技术文档 |
| 尾注 | 文档末尾 | 书籍、长篇报告 |
| 行内注释 | 紧跟正文 | 简短补充 |
Markdown 中的脚注实际上是尾注——所有脚注内容统一显示在文档末尾。
1.3 心智模型:标记与定义是靠标签配对的两个独立元素
学脚注最容易卡住的地方是”定义到底写在哪”。正确的模型是把它想成变量与引用:
[^note]是引用标记:写在正文里,决定”哪里出现上标”;[^note]: 内容是定义:写在文档任何位置,决定”点开上标看到什么”;- 两者只靠标签名(
note)配对,物理位置完全分离。
由此直接推出三条规则(不用死记):
- 定义写在哪都不影响渲染——渲染器扫描全文收集定义,统一搬到末尾;
- 显示编号是渲染器按”引用出现顺序”自动编排的,与标签名无关:
[^zuihou]若是正文第一个被引用的脚注,就显示为 [1]; - 没有被任何标记引用的定义是”未使用的变量”——多数渲染器(含 GitHub)直接不渲染它,写了对不引用等于没写。
这套”正文干净、定义后置、按名配对”的结构,与参考式链接是同一个思想:长文档里把资源定义集中管理,正文只留短引用。
2. 脚注语法
2.1 基本语法
这是一段正文[^1],其中包含脚注引用。
也可以使用描述性标签[^note]。
[^1]: 这是第一个脚注的内容。
[^note]: 这是描述性标签的脚注内容。渲染效果:
- 正文中的
[^1]显示为上标数字 [^1] - 点击上标可跳转到文末脚注
- 文末脚注带有返回链接
2.2 脚注定义规则
<!-- 规则一:脚注定义可放在文档任意位置 -->
正文内容[^1]。
<!-- 脚注定义可以放在文档末尾 -->
[^1]: 脚注内容。
<!-- 规则二:脚注定义需要空行分隔 -->
[^1]: 第一个脚注。
[^2]: 第二个脚注。
<!-- 规则三:多行脚注使用缩进 -->
[^long]:
这是第一行。
这是第二行(缩进4个空格)。
这是第三行。规则一的深一层读法:正因为”定义位置无关渲染”,实践里才有一条团队约定——定义统一放文末。渲染结果相同,但定义散落正文会让后续维护者找不到”所有脚注”的全景,文末集中存放让脚注清单本身成为文档的参考文献区。
2.3 脚注标签类型
| 类型 | 语法 | 显示效果 | 适用场景 |
|---|---|---|---|
| 数字标签 | [^1] | [1] | 顺序引用 |
| 描述标签 | [^source] | [source] | 语义化引用 |
| 混合使用 | [^1] [^note] | 各自显示 | 灵活场景 |
实践建议:标签一律用语义化命名([^bench]、[^rfc9110]),数字标签只留给”注定一次性”的脚注。原因与变量命名相同:后来者在正文里看到 [^4] 无法知道它是什么,看到 [^perf-data] 可以;而且在中间插入一个新脚注时,语义化标签不需要把后续所有编号重排一遍(显示编号本来就是自动的)。
3. 多平台支持
3.1 支持情况
| 平台 | 支持脚注 | 语法 | 说明 |
|---|---|---|---|
| GitHub | 支持 | [^1] | 2021 年 9 月起全站支持 |
| GitLab | 支持 | [^1] | 原生支持 |
| Obsidian | 支持 | [^1] | 原生支持,支持行内脚注 |
| Typora | 支持 | [^1] | 原生支持 |
| Hugo | 支持 | [^1] | Goldmark 默认启用 |
| Jekyll | 视配置 | [^1] | 依赖所用 Markdown 处理器 |
| CommonMark | 不支持 | — | 标准不支持 |
| GFM 规范文档 | 未收录 | — | 脚注是 cmark-gfm 扩展,未写入正式规范文档 |
这张表是”扩展语法的平台税”的典型样本:功能好用,但不在 CommonMark 核心里。跨平台发布的文档(同一份 md 既进 GitHub 又进静态站点又进 PDF 转换)要先用目标渲染器过一遍,脚注尤其如此——它一旦不被支持,[^1] 会原样出现在正文里,比”功能缺失”更难看。
3.2 GitHub 脚注
GitHub 于 2021 年 9 月正式支持脚注语法(cmark-gfm 的 footnotes 扩展):
GitHub 现在支持脚注了[^1]!
[^1]: 2021 年 9 月,GitHub 宣布在所有 Markdown 字段支持脚注语法。GitHub 脚注特性:
- 脚注内容显示在文档底部
- 点击上标跳转到脚注
- 脚注旁有返回箭头
- 数字标签自动编号
3.3 Obsidian 脚注
Obsidian 支持标准脚注语法,还支持行内脚注:
<!-- 标准脚注 -->
正文内容[^1]。
[^1]: 脚注定义。
<!-- 行内脚注(Obsidian 特有) -->
正文内容^[这是行内脚注,无需单独定义。]行内脚注把”标记与定义分离”的模型重新合体:内容就地写,渲染时仍搬到文末。它解决了”短注释不想跳到文末维护”的场景,但这是 Pandoc/Obsidian 私有语法——写进要发到 GitHub 的文档会原样暴露 ^[...]。跨平台文档用标准语法,个人笔记库才用行内脚注。
4. 脚注高级用法
4.1 多次引用同一脚注
TypeScript[^ts] 是 JavaScript 的超集。
TypeScript[^ts] 添加了静态类型检查。
[^ts]: TypeScript 由 Microsoft 开发,2012 年首次发布。同一脚注可以多次引用,渲染时使用相同的上标标记。典型场景:多个论断共享同一个来源——来源只列一次,引用处处可点。
4.2 脚注中的 Markdown
脚注内容支持行内 Markdown 语法:
正文引用[^api]。
[^api]: 参见 [API 文档](https://example.com/api) 中关于 `fetch()` 方法的说明。边界提示:脚注内容里不能再嵌套脚注(标记会被当字面文本),也不支持块级元素;多行内容用 2.2 的缩进续行写法。
4.3 学术引用格式
根据 Smith 等人的研究[^smith2023],深度学习在自然语言处理领域取得了显著进展。
[^smith2023]: Smith, J., et al. "Deep Learning for NLP: A Survey." _Journal of AI Research_, vol. 45, 2023, pp. 123-156.5. 常见坑
坑一:定义了但没引用,脚注消失。 [^x]: 内容 写了,正文却没有 [^x] 标记——渲染器不输出它(见 1.3 的”未使用变量”类比)。排查顺序固定:先全文搜标记,再搜定义,两端都要在。
坑二:标签重复定义。 两处写了 [^1]: ...,不同渲染器行为不一(取第一个或取最后一个),结果不可预测。语义化命名(坑外的建议同 2.3)能大幅降低撞名概率。
坑三:多行内容没缩进。 续行顶格写会被当成新段落,脱离脚注;续行必须缩进(4 空格或与首行内容对齐)。
坑四:在脚注里再放脚注或代码块。 标记原样显示、代码块被切断。脚注里只有行内语法可用。
坑五:把脚注当评论系统用。 大段设计讨论、给协作者的留言塞进脚注,文档会越来越难读。脚注是”补充证据与出处”,不是评论区——那种内容该去 issue 或 PR 讨论。
6. 替代方案
6.1 不支持脚注时的替代
当目标平台不支持脚注时,可以使用以下替代方案:
方案一:行内链接
根据研究[1],结论如下。
[1] Smith, J. "Deep Learning Survey." 2023.方案二:HTML 锚点
根据研究<a href="#ref1">[1]</a>。
<a name="ref1"></a>
1. Smith, J. "Deep Learning Survey." 2023.方案三:引用块
根据研究[1],结论如下。
> **[1]** Smith, J. "Deep Learning Survey." 2023.三种替代的共同思路是手工模拟”标记 + 文末定义”:方案一连跳转都没有,方案二用 HTML 恢复跳转,方案三至少让来源在视觉上成组。它们都失去了自动编号——这正是标准脚注不可替代的部分。
6.2 Pandoc 脚注
Pandoc 支持更丰富的脚注语法:
<!-- 行内脚注 -->
正文^[这是行内脚注。]
<!-- 引用式脚注 -->
正文[^cite]
[^cite]: Smith, J. "Paper Title." 2023.7. 动手实践:遮代码自检
先只读任务与提示,自己写完再对照参考实现。
任务:把下面这段”行内括号注释”风格的文字改写成标准脚注版,要求——三个补充说明全部变成脚注;其中”发布年份”这个来源被正文两处引用(只定义一次);脚注标签全部语义化;脚注内容里带一个链接。
Rust(发布于 2015 年,1.0 版,Mozilla 主导)是一门系统级语言。它的所有权模型(详见官方 Book,链接 https://doc.rust-lang.org/book/)让内存安全无需垃圾回收。2024 年 Rust 已进入 Linux 内核(6.1 起合入初步支持)。
提示:先找出三个”括号里”的信息块(发布信息 /所有权 Book / 内核支持),分别给语义化标签;注意”发布于 2015 年”与”Mozilla 主导”要共用同一个来源标记(回看 4.1)。
参考实现(先自己写完再看):
Rust[^rust-release] 是一门系统级语言。它的所有权模型[^rust-book]让内存安全
无需垃圾回收。2024 年 Rust 已进入 Linux 内核[^rust-kernel]。
[^rust-release]: 1.0 版发布于 2015 年,由 Mozilla 主导,另见
[Rust Blog](https://blog.rust-lang.org)。
[^rust-book]: 官方教程见 [The Rust Programming Language](https://doc.rust-lang.org/book/)。
[^rust-kernel]: Linux 6.1 起合入 Rust 初步支持,状态见内核邮件列表存档。要点自查:三个标签都是语义化的;[^rust-release] 在正文只出现一次但承担了两个括号的信息——若原文明里两处提到”2015”,就该引用两次;链接写在脚注定义内(4.2);多行定义的续行有缩进(坑三)。
8. 与之前和之后的知识的关系
- 往前:链接与图片 的参考式链接是脚注的结构前身——都是”正文短引用、定义集中管理”;自动链接 解释了脚注里裸 URL 与带文字链接的差异;
- 横向:转义字符 中
[^不属于需转义字符,脚注标记不会被转义打碎; - 往后:规范文档写作 里,脚注承接”引用标准、给出处”的角色;写学术论文或 RFC 风格文档时,1.1 的信息分层思想会反复用到。
小结
- 初学者要点:正文写
[^1]标记、文末写[^1]: 内容定义;GitHub、GitLab、Obsidian、Typora 都支持;点击上标跳转、脚注旁可返回。 - 进阶注意:脚注是扩展语法而非 CommonMark 核心,纯规范渲染器原样显示;心智模型是”标记与定义靠标签配对的两个独立元素”——定义位置无关渲染、显示编号按引用顺序自动编排、未被引用的定义不渲染;标签建议语义化命名;行内脚注
^[...]是 Pandoc/Obsidian 私有语法,GitHub 不支持;同一标签可多处引用;不支持脚注的平台用”手写编号 + 文末列表”兜底,但失去自动编号。