Markdown 分栏完全指南 - 多栏布局方法与代码示例
每次想在 Markdown 里并排放两段内容,就会发现 Markdown 根本没有分栏语法。没有 :::columns,没有 {.split},什么都没有。
这其实说得通。Markdown 的设计初衷是"易读易写的纯文本格式" [^1],而多栏布局本质上是排版问题,不是纯文本该操心的事。但这不代表你完全没办法——这篇文章会把你能在 Markdown 里用到的所有分栏方法讲清楚,包括哪些场景能用、哪些平台不支持、以及每种方法的具体代码。
为什么 Markdown 没有原生的分栏语法?
先说结论:CommonMark 规范 [^1] 和 GitHub Flavored Markdown(GFM)都没有定义任何分栏或多栏语法。这不是遗漏,而是刻意的设计选择。
Markdown 的核心哲学是"源码本身就应该是可读的"。多栏布局是视觉层面的东西——一个纯文本文件没法表达"左边放 A、右边放 B"这种空间关系。你在纯文本里看到一左一右两段文字,不借助渲染器根本看不出它们是并排的。
所以如果你需要在 Markdown 里做分栏,所有方法本质上都是在 Markdown 里嵌入 HTML 和 CSS。理解了这一点,后面的内容就不会让你意外了。
方法一:HTML + CSS Flexbox(最常用)
这是目前最通用、最灵活的分栏方法。原理很简单:用 HTML 的 <div> 标签搭配 CSS Flexbox 布局。
基本双栏布局
<div style="display: flex; gap: 20px;">
<div style="flex: 1;">
### 左栏内容
这里是左栏的 Markdown 内容。
</div>
<div style="flex: 1;">
### 右栏内容
这里是右栏的 Markdown 内容。
</div>
</div>几个关键点:
display: flex开启弹性布局flex: 1让两栏等宽,改成flex: 2就能让某一栏更宽gap: 20px控制栏间距- 每个
<div>内部可以正常写 Markdown——前提是你的渲染器支持 HTML 块内的 Markdown 解析
有一次我给项目写 README,兴冲冲写了两个 <div style="flex:1"> 想把接口说明和示例代码并排显示,推到 GitHub 上一看——两段内容老老实实上下排列,style 属性被直接删掉了。后来才搞清楚 GitHub 出于安全考虑会过滤所有自定义样式 [^3]。
三栏布局
把结构扩展一下就行:
<div style="display: flex; gap: 16px;">
<div style="flex: 1;">
#### 第一栏
内容 A
</div>
<div style="flex: 1;">
#### 第二栏
内容 B
</div>
<div style="flex: 1;">
#### 第三栏
内容 C
</div>
</div>不等宽分栏
如果需要侧边栏效果(比如 3:7 比例):
<div style="display: flex; gap: 20px;">
<div style="flex: 3;">
### 主内容区
这里是主要内容。
</div>
<div style="flex: 7;">
### 侧边栏
这里是辅助信息。
</div>
</div>Flexbox 的优势在于它足够灵活——改一个数字就能调整栏宽比例,加一个 <div> 就能增加栏数。缺点是代码比较冗长,而且不是所有 Markdown 渲染器都支持在 HTML 标签内解析 Markdown 语法。这个问题在后面"平台兼容性"部分会详细说。
方法二:HTML + CSS Grid
CSS Grid 是另一种现代布局方案。和 Flexbox 的区别在于 Grid 更擅长二维布局——行和列同时控制。对于简单的分栏场景,Grid 和 Flexbox 效果差不多,但 Grid 写法可以更简洁:
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
### 左栏
左栏内容。
### 右栏
右栏内容。
</div>三栏的写法:
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px;">
#### 栏一
内容 A
#### 栏二
内容 B
#### 栏三
内容 C
</div>Grid 的好处是 grid-template-columns 这一行就能定义栏数和比例,比如 2fr 1fr 表示左栏占 2/3、右栏占 1/3。相比 Flexbox 需要在每个子元素上写 flex 属性,Grid 把布局逻辑集中在一个地方,代码更干净。
不过和 Flexbox 一样,Grid 的实际效果完全取决于你的渲染环境是否支持。
方法三:CSS column-count(适合纯文本多栏)
如果你的分栏需求是"把一段长文字自动分成多栏显示"(类似报纸排版),CSS 的 column-count 属性 [^2] 是最直接的方案:
<div style="column-count: 2; column-gap: 30px;">
这是一段很长的文字内容。当内容足够长时,浏览器会自动将其分成两栏显示,就像报纸的排版一样。这种方法不需要手动分割内容,浏览器会根据容器宽度自动计算每栏的高度和内容分配。
适合用在引用块、长段落、或者列表内容的自动分栏展示上。如果你的内容比较短,可能看不出分栏效果,因为 column-count 只在内容溢出时才会产生真正的多栏。
</div>三栏只需要改一个数字:
<div style="column-count: 3; column-gap: 24px;">
长文本内容...
</div>column-count 和 Flexbox/Grid 的最大区别在于:column-count 是自动流式分栏——你不需要手动决定哪些内容放左栏、哪些放右栏,浏览器会自动把内容按顺序分配到各栏。而 Flexbox/Grid 需要你明确划分每个栏的内容。
什么时候用 column-count:
- 长段落的自动分栏(类似新闻排版)
- 列表项的自动多栏展示
- 不需要手动控制每栏内容的场景
什么时候不用:
- 需要左右栏放不同内容(比如左边代码、右边说明)
- 栏内需要包含复杂的 Markdown 元素(标题、代码块等可能被截断)
方法四:用表格模拟分栏
在不想用 HTML 的情况下,Markdown 表格可以模拟一个"看起来像分栏"的效果:
| 左栏 | 右栏 |
|------|------|
| 这里是左边的内容,可以是文字、链接等 | 这里是右边的内容 |
| 支持多行内容 | 每一行就是一个"行" |这个方法的优点是纯 Markdown 语法,几乎所有渲染器都支持。缺点也很明显:
- 语义不对:表格是用来展示数据的,不是用来做布局的。对屏幕阅读器等辅助工具来说,这会产生错误的语义信息
- 格式受限:表格单元格里不能放标题、代码块、引用等块级元素,只能放行内内容
- 不好控制宽度:列宽由内容自动决定,没法精确控制
表格模拟分栏只适合简单场景——如果就是想在两边各放一段文字,不想写 HTML,那表格够用了。但凡内容复杂一点,还是老老实实用 HTML+CSS。
说实话,这几种方法里,Flexbox 是我日常用得最多的。大部分 Markdown 编辑器和静态站生成器都吃这一套,写起来也不算太麻烦。
各平台的分栏支持情况
上面的方法理论上都能用,但实际效果取决于你用的平台和工具。这里说说几个常见平台的具体情况——踩坑踩出来的经验,别走我的老路。
Obsidian
Obsidian 支持在 Markdown 中使用 HTML 标签,所以 Flexbox 和 Grid 方法都能生效。但 Obsidian 有一个更好的方案:CSS Snippets [^4]。
你可以在 Obsidian 的 CSS snippets 文件夹中创建一个 CSS 文件,定义分栏样式:
/* 在 .obsidian/snippets/ 文件夹中创建 columns.css */
.columns-two {
display: flex;
gap: 20px;
}
.columns-two > div {
flex: 1;
}然后在 Markdown 中使用:
<div class="columns-two">
### 左栏
内容...
<div>
### 右栏
内容...
</div>
</div>CSS snippets 的好处是把样式逻辑和内容分开,Markdown 文件更干净。
不过有个细节要注意:Obsidian 的"阅读视图"和"实时预览"模式对 HTML 的渲染行为不完全一致。我实测发现,在阅读视图里 Flexbox 分栏效果正常,但实时预览模式下偶尔会出现 <div> 标签被原样显示的情况。所以如果你用 Obsidian,建议以阅读视图的效果为准。
另外,Obsidian 社区有个 Multi-Column Markdown 插件,提供了 ---start-multi-column--- 这种自定义语法来做分栏。功能很强大,支持设置栏宽比例、边框、阴影等。缺点是这些语法只在 Obsidian 里有效,换到别的编辑器就是一堆废代码。
MkDocs(静态站点生成器)
如果你用 MkDocs 搭建文档站,MkDocs Material 主题内置了 Grid 和 Tab 功能 [^5]。使用方式是扩展的 Markdown 语法:
<div class="grid cards" markdown>
- ## 卡片一
内容 A
- ## 卡片二
内容 B
</div>这比手写 CSS 方便很多,但只限于 MkDocs Material 主题。其他静态站点生成器(Hugo、Jekyll 等)通常也支持在模板中使用 HTML+CSS 分栏,但需要自己写样式。
Hugo 用户可以利用 Hugo 特有的 markdown attribute 功能,在内容块后面加 {.c .c2} 这样的类名标记,再配合 CSS 实现分栏。这个方案比直接写 HTML 干净,但只对 Hugo 有效。
GitHub
这是很多人踩坑的地方:GitHub 渲染 Markdown 时会过滤掉 HTML 中的 style 属性 [^3]。也就是说,上面所有带 style="display: flex" 的代码,在 GitHub 上都不会生效——style 属性会被直接删除。
所以在 GitHub README 或 Issues 中,Flexbox、Grid、column-count 这些方法全都用不了。你能用的只有表格模拟分栏,而且效果很有限。
GitHub 出于安全考虑,只允许少量的 HTML 标签和属性通过渲染,所有自定义样式都会被过滤。这是刻意的设计选择,不是 bug。
如果你确实需要在 GitHub 上做并排展示,唯一的"正经"方案是用 HTML <table> 标签(不带 style),而且只能在 <td> 里放行内内容。这跟纯 Markdown 表格差不多,不过 HTML table 在 <td> 里解析 Markdown 的兼容性更好一些。
其他编辑器
- Typora:支持 HTML+CSS 分栏,因为 Typora 本质上是本地浏览器渲染,完整的 CSS 都能用
- VS Code 预览:取决于你用的预览插件。大部分插件的预览窗口是本地浏览器,所以 HTML+CSS 方法通常有效
- Notion:不是标准 Markdown,有自己原生的分栏功能(拖拽即可),和本文讨论的方法无关
- Pandoc:通过 fenced divs(
::::)可以定义内容块,配合 CSS 能实现分栏,适合生成 PDF 的场景
响应式:分栏在手机上怎么办?
Flexbox 和 Grid 默认不会自动在小屏幕上变成单栏。如果你需要响应式,得加上 flex-wrap: wrap(Flexbox)或使用媒体查询。
在纯 Markdown 环境中加媒体查询比较困难——你没法在单个 Markdown 文件里写 @media 规则。这通常需要在站点级别的 CSS 中处理。如果你的分栏内容是发布在网站上的,建议在外部 CSS 中加上:
@media (max-width: 768px) {
.columns-two, .columns-three {
flex-direction: column;
}
}对于 Obsidian 用户来说,这个不是问题——Obsidian 本身没有"手机版"渲染。但如果你的 Markdown 是发布到网上的,响应式就是必须要考虑的事。
方法对比:什么时候用什么
根据使用场景,这里有一个快速选择指南:
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 个人笔记(Obsidian) | CSS Snippets | 样式复用,内容干净 |
| 文档站(MkDocs) | 内置 Grid 组件 | 主题原生支持,效果最好 |
| 文档站(Hugo) | markdown attribute + CSS | Hugo 特有方案,代码干净 |
| 静态网站 | Flexbox 或 Grid | 完全控制,兼容性好 |
| GitHub README | 表格模拟 | 唯一能用的方法 |
| 长文本自动分栏 | column-count | 自动分配,无需手动切分 |
| 博客/通用 Markdown | Flexbox | 兼容性最广的方案 |
| 生成 PDF | Pandoc fenced divs + CSS | 兼顾 HTML 和 LaTeX 输出 |
还有一个需要提前确认的事:你的 Markdown 渲染器是否支持在 HTML 标签内解析 Markdown。有些渲染器(如 kramdown、MkDocs 的渲染器)支持在 HTML 块内解析 Markdown,有些则不支持。如果渲染器不支持,那 <div> 内部的 Markdown 语法会原样显示出来。
一个简单的判断方法:写个测试文件,在 <div> 里放一个 ### 测试标题,看看渲染出来是标题格式还是纯文本。如果是纯文本,说明你的渲染器不支持 HTML 块内 Markdown 解析,需要把内容也写成 HTML。
常见问题
分栏在手机上会怎样?
Flexbox 和 Grid 默认不会自动在小屏幕上变成单栏。如果需要响应式,需要在外部 CSS 中加上媒体查询,或者在 Flexbox 中使用 flex-wrap: wrap。对于纯 Markdown 文件来说,这通常需要在站点级别处理。
有没有 Markdown 扩展支持原生分栏?
目前主流的 Markdown 扩展中没有被广泛采用的分栏语法。Pandoc 的 fenced divs(::::)可以定义内容块,但本身不提供分栏样式——还是需要搭配 CSS。一些平台(如 Gitiles)有自己的扩展语法(|||---|||),但仅限那个平台。这再次说明分栏本质上是样式问题,不是语法问题。
为什么我的分栏代码不生效?
最常见的原因有三个:
- 平台过滤了 style 属性:GitHub 和部分在线编辑器会删除 inline style
- 渲染器不支持 HTML 块内的 Markdown:
<div>里的 Markdown 被原样显示 - 内容太短:column-count 需要内容足够多才能看到分栏效果
建议先确认你的平台支持哪种方法,再选择对应的方案。
参考来源
[^1]: CommonMark Spec: https://spec.commonmark.org/[^2]: MDN Web Docs - CSS Multi-column Layout: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout[^3]: GitHub Docs - Basic writing and formatting syntax: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax[^4]: Obsidian Help - CSS Snippets: https://help.obsidian.md/Extending+Obsidian/CSS+snippets[^5]: MkDocs Material - Grids: https://squidfunk.github.io/mkdocs-material/reference/grids/