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 + CSSHugo 特有方案,代码干净
静态网站Flexbox 或 Grid完全控制,兼容性好
GitHub README表格模拟唯一能用的方法
长文本自动分栏column-count自动分配,无需手动切分
博客/通用 MarkdownFlexbox兼容性最广的方案
生成 PDFPandoc 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)有自己的扩展语法(|||---|||),但仅限那个平台。这再次说明分栏本质上是样式问题,不是语法问题。

为什么我的分栏代码不生效?

最常见的原因有三个:

  1. 平台过滤了 style 属性:GitHub 和部分在线编辑器会删除 inline style
  2. 渲染器不支持 HTML 块内的 Markdown<div> 里的 Markdown 被原样显示
  3. 内容太短: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/