By Arthur Teboul//12 min read/Tutorial

Markdown Columns: Two Column and Side-by-Side Layout (2026)

TL;DR: No Markdown specification has a column syntax — not CommonMark, not GFM. The portable answer is a GFM table with empty headers, which works everywhere but gives you no width control. Everything else (HTML tables, flex divs, Pandoc fenced divs, MkDocs grids) trades portability for control, and which one survives depends entirely on what the renderer's HTML sanitizer allows.

Markdown columns do not exist as syntax. There is no ::: block, no pipe trick, no bracket form that any specification turns into a side-by-side layout — every technique in this guide is HTML or CSS that the renderer happens to let through. Which means the question "does this tool support columns?" is really the question "what HTML does this tool's sanitizer allow?", and that has a different answer on GitHub, in Obsidian, in Pandoc, and in a local viewer like MacMD Viewer.

That reframe is the whole article. Below: the one route that works everywhere, the HTML routes and exactly where each dies, the tools that do have a real column syntax, and a platform matrix built from the sanitizer allowlists rather than from guesswork.

Are Markdown Columns Part of the Spec?

No. CommonMark 0.31.2 defines exactly three container block types — block quotes, list items and lists — and none of them is a column, grid or side-by-side construct. GitHub Flavored Markdown adds five extensions on top of that (tables, task list items, strikethrough, autolinks, disallowed raw HTML) and not one of them is layout.

What the spec does give you is a hole, and every column workaround goes through it. Section 4.6 on HTML blocks says that any HTML inside an HTML block "will be ignored by the parser and passed through as-is, without changing the parser's state." Markdown delegates layout to HTML instead of defining it.

So the moment you write a column, you have left Markdown and entered someone else's allowlist. GitHub's own formatting documentation documents raw HTML support and Markdown tables, and contains no column construct anywhere. That is not an oversight — there is nothing to document.

Side-by-Side Columns and Flowing Columns Are Different Problems

Before picking a technique, decide which layout you actually want, because the two have almost nothing in common.

Side-by-side columns place two or more independent contents next to each other: a screenshot beside its caption, install instructions for macOS beside Linux, a before-and-after code pair. Tables and flexbox do this.

Flowing columns take one stream of text and reflow it into several columns, newspaper-style, so a sentence that overruns column one continues at the top of column two. CSS column-count does this.

Most people searching for Markdown columns want the first and land on articles about the second. If your content is two separate things, column-count is the wrong tool — it will pour them into one stream and split them wherever the height happens to run out.

How Do You Make Two Column Markdown with a Table?

Use a GFM table and leave the header cells empty. This is the recommendation for anything that has to survive being read somewhere you do not control, because it is real Markdown rather than HTML that a sanitizer might strip:

|  |  |
|---|---|
| **macOS**<br>`brew install foo` | **Linux**<br>`apt install foo` |

Four limits, all traceable straight to the tables extension:

  • The delimiter row is mandatory. You cannot write a headerless table. You can only leave the header cells blank, as above.
  • Alignment has three forms and no more: :--- left, :---: centre, ---: right. There is no width, no padding, no vertical alignment.
  • Cells hold inline content only. No blank lines, no multiple paragraphs, no nested fenced code blocks. This is the limit people hit first and hardest.
  • Line breaks need <br>. Pressing Enter inside a cell ends the row.

That last pair of restrictions is what pushes people toward raw HTML. If your column content is a paragraph and a code sample, a GFM table will not hold it. If your column content is a label and a command, it will, and it will render identically in every tool you paste it into. The Markdown table guide covers the alignment and escaping rules in full.

How Do You Use HTML for Markdown Multi Column Layouts?

Two HTML routes exist, and they fail on opposite platforms. Neither is universal.

The <table> route

This is the trick GitHub READMEs use, because presentational attributes survive there even though CSS does not:

<table>
<tr>
<td width="50%" valign="top">
 
Markdown **works here** as long as you leave blank lines around it.
 
</td>
<td width="50%" valign="top">
 
Second column.
 
</td>
</tr>
</table>

Those blank lines inside <td> are load-bearing. Without them the parser is still inside a raw HTML block and your bold text stays literally asterisked — the same CommonMark boundary rule that governs collapsible sections.

The <div> and flexbox route

Shorter, cleaner, and stripped on every major forge:

<div style="display: flex; gap: 1rem;">
  <div style="flex: 1;">Left</div>
  <div style="flex: 1;">Right</div>
</div>

This survives wherever the renderer keeps the style attribute: Typora, Obsidian and the VS Code preview all do. It does not survive on GitHub or GitLab, both of which sanitize to an allowlist with no style entry. And it is not the right form for MDX at all, for a reason covered further down.

One trap specific to Obsidian, from its own HTML content documentation: "Markdown doesn't process inside HTML elements", and HTML blocks "cannot contain blank lines". So you cannot wrap Markdown-formatted prose in a styled div there and expect it to render as Markdown — the blank line that rescues you on GitHub breaks you in Obsidian.

The finding that decides which route to use

Here is the part nobody mentions. html-pipeline — the sanitization library GitHub open-sourced and the one GitLab's docs name — has zero occurrences of style and zero of class in its allowlist, while align, width, valign, colspan and rowspan all appear in its global attribute list. That is the precise version of the vague "GitHub strips CSS" claim that circulates everywhere.

I wrote MacMD Viewer's sanitizer, and it makes the opposite call. At v1.5.1, td and th allow exactly style, colspan and rowspan — so inline CSS on a cell works and width does not:

Attribute on a table cellhtml-pipeline (GitHub, GitLab)MacMD Viewer v1.5.1
styleStrippedKept
widthKeptStripped
align / valignKeptStripped
colspan / rowspanKeptKept

A hand-tuned HTML table therefore cannot be width-controlled in both at once. Whichever attribute you reach for, one of the two renderers throws it away. That is the strongest argument there is for the plain GFM table: it is the only form where the layout is expressed in Markdown itself and nothing in the middle can drop it.

Which Tools Have a Real Column Syntax?

Four ecosystems went past HTML and defined something.

Pandoc comes closest. The fenced_divs extension starts a div with at least three consecutive colons plus attributes, and the Columns section of the manual documents the layout form directly: "To put material in side by side columns, you can use a native div container with class columns, containing two or more div containers with class column and a width attribute."

:::::::::::::: {.columns}
::: {.column width="40%"}
contents...
:::
::: {.column width="60%"}
contents...
:::
::::::::::::::

Worth noting where the manual puts this: the Columns section sits inside the slide-shows chapter, so it is documented as presentation layout rather than as general-purpose page layout. Beamer output additionally accepts an align attribute (top, top-baseline, center and bottom, defaulting to top on columns), a totalwidth attribute that limits the total width of the columns, and an onlytextwidth class. One documented limitation to plan around: "Specifying column widths does not currently work for PowerPoint."

MkDocs Material has grids — wrap a set of blocks in a div with the grid class, or an unordered list in a div with both grid and cards. Two things the examples will not tell you: it needs version 9.5.0 or later, and it needs both the attr_list and md_in_html extensions enabled in mkdocs.yml. Omit either and the example fails silently, which is the worst kind of broken. Both grid types are marked experimental in the docs.

Docusaurus and MDX need JSX, not HTML. The Docusaurus docs are explicit that "anything that looks like HTML is actually JSX", so inline styles must be objects: style={{display: 'flex', gap: '1rem'}}. A style="..." string does not merely render wrong — it fails to compile.

Obsidian has the Multi-Column Markdown community plugin, which supports Pandoc-style fenced divs among three syntaxes and has 211,328 downloads. Be aware of its state before you build a vault on it: the last release (0.9.1) shipped on 2024-01-15 and the last repository activity was 2024-05-19. It is still installable and still widely used, but it has not been developed in over two years.

Which Platforms Support Markdown Columns?

The style column is the one that decides everything.

PlatformNative column syntaxRaw HTMLstyle attributePractical route
CommonMark (spec)NoPassed through as-isRenderer's callGFM table
GitHubNoAllowlisted subsetStrippedGFM table, or <table> with width/valign
GitLabNoAllowlisted subsetStrippedSame as GitHub
ObsidianNoYes, sanitizedAllowedInline-style divs, or the dormant plugin
TyporaNoYesAllowed on inline tags; class/id unsupportedInline-style divs
VS Code previewNoYesAllowedInline-style divs
JupyterNoYesHTML tables
PandocYes::: columnsYesYesFenced divs
MkDocs MaterialGrid classes (≥9.5.0, experimental)Via md_in_htmlYes<div class="grid" markdown>
Docusaurus / MDXNoJSX, not HTMLJSX object onlyFlex div with a style object
NotionNoBlock editorEditor columns, not .md syntax
MacMD ViewerNoAllowlisted subsetOnly on <td> / <th>HTML table with <td style="width:50%">

Two rows worth expanding. Notion has no Markdown column syntax at all — columns there are something you build in the editor, not something you can type into a .md file. And VS Code is the subject of a persistent myth: several sources claim its preview does not render raw HTML. That is wrong. The preview constructs markdown-it with html: true; what the Strict security setting blocks is script execution and http images, not HTML elements or inline styles.

How Do You Get Newspaper-Style Flowing Columns?

Use CSS, and only where you control the stylesheet. The CSS Multi-column Layout Module Level 1 defines column-count, column-width and the columns shorthand; setting either column-count or column-width to a non-auto value establishes a multi-column container.

<div style="column-count: 2; column-gap: 2rem;">
 
One continuous stream of text that reflows across both columns.
 
</div>

This is the right tool for print and PDF, where the spec has a useful guarantee: if the multi-column container is paginated, the height of each column is constrained by the page and content continues in a new line of column boxes on the next page — a column box never splits across pages. For Markdown-authored slide decks, Marp lets you write your own theme in plain CSS, which is the same route.

But note what just happened: that div carries a style attribute, so on GitHub or GitLab it degrades to one plain block of text. Flowing columns are a styling feature, and styling is exactly what forges strip.

Common Markdown Column Mistakes

Five failures cover almost everything, and four of them are silent.

Using inline style on a forge. The div survives, the attribute does not, and the columns stack vertically with no warning. Reach for <td width="50%"> there instead.

Putting multi-paragraph content in a GFM table cell. Cells are inline-only. A blank line ends the table; a fenced code block inside a cell does not parse. If the content needs paragraphs, you need the HTML table route.

Writing style="..." in MDX. MDX is JSX. It needs style={{…}} and will fail the build rather than render badly, which at least makes this the one loud failure in the list.

Reaching for column-count when you wanted side-by-side. Two separate contents poured into one flowing stream will split at an arbitrary height, not between your two items.

Enabling one MkDocs extension instead of two. Grids need both attr_list and md_in_html. Enable only one and the grid never forms — no layout is applied, and the Markdown inside the div stops being processed as Markdown.

How Do You Preview Markdown Columns on Mac?

macOS ships no Markdown renderer, so a .md file with a column layout opens in TextEdit as raw tags. What you need is a viewer whose sanitizer you know, because that is the only thing that determines whether your columns appear.

MacMD Viewer renders both portable routes: plain GFM tables, and HTML tables with inline-styled cells, since style is allowed on td and th. So this genuinely produces two columns:

<table>
<tr>
<td style="width:50%; vertical-align:top">Left</td>
<td style="width:50%; vertical-align:top">Right</td>
</tr>
</table>

Being straight about the other direction: <div style="display:flex"> does not produce columns in MacMD. The div survives, the style attribute is dropped, and the children stack. Class-based grids do not work either, because no shipped stylesheet acts on those classes. If your layout depends on flexbox, check it in the tool that will actually display it.

Where the app earns its keep on this particular problem is the feedback loop. It live-reloads on save, so you can watch a column layout appear or collapse as you edit, and it renders the same file in QuickLook — press Space on a README in Finder and see the layout without opening anything. For a wider comparison of local viewers, see the best Markdown viewer roundup, and for the rest of the syntax, the Markdown cheat sheet.

Frequently Asked Questions

Does Markdown support columns natively?

No. CommonMark 0.31.2 defines three container block types — block quotes, list items and lists — and none of them is a column. GitHub Flavored Markdown adds five extensions on top, none of them layout-related. Every column technique in Markdown is raw HTML or CSS passed through by the renderer.

How do you make two column Markdown?

Use a GFM table with two columns and empty header cells. It is the only route that works everywhere, because it is real Markdown rather than HTML the platform might strip. The tradeoff is that a table cell holds inline content only — no blank lines, no multiple paragraphs, no fenced code blocks.

Why does my flexbox div not render columns on GitHub?

GitHub sanitizes HTML against an attribute allowlist that has no style entry, so <div style="display: flex"> loses the attribute and the children stack vertically. The element itself survives — only the styling is dropped. The same applies to class, so CSS-class-based grids fail there too.

Can you set the width of a Markdown column?

Not in a plain GFM table — the syntax has no width control at all. In raw HTML it depends on the renderer's allowlist: GitHub keeps the legacy width attribute on cells but strips style, while some local viewers do the reverse. A hand-tuned HTML table cannot be width-controlled in both at once.

What is the difference between side-by-side columns and CSS multi-column?

Side-by-side means two independent contents placed next to each other, which is what tables and flexbox do. CSS multi-column reflows a single stream of text into several columns like a newspaper, which is what column-count does. Most people searching for Markdown columns want the first and find articles about the second.

Does Obsidian support Markdown columns?

Not natively. Obsidian keeps the style attribute on sanitized HTML, so an inline-styled flex div works, but its documentation warns that Markdown does not process inside HTML elements and that HTML blocks cannot contain blank lines. The Multi-Column Markdown community plugin adds a real column syntax, though it has not shipped a release since January 2024.

How do you write columns in Pandoc?

Pandoc's fenced_divs extension gives the closest thing to a real column syntax: a div with class columns containing two or more divs with class column and a width attribute. The manual documents it in the slide-shows chapter, with extra align, totalwidth and onlytextwidth attributes for Beamer output, and notes that specifying column widths does not currently work for PowerPoint.

Read your Markdown files the way they’re meant to look.

Native macOS viewer with QuickLook preview, Mermaid diagrams, syntax highlighting, and live file-watching. $19.99 one-time, no subscription.

Buy for $19.99

Content licensed under CC BY 4.0. Cite with attribution to MacMD Viewer.

Related Articles

Tutorial

Markdown Highlight: ==text== and the <mark> Tag (2026)

Markdown highlight has no spec syntax. ==text== works in Obsidian and Bear; <mark> is the portable HTML route. Platform table, GitHub test, and fallbacks.

Tutorial

Markdown Small Text: Subscript, Superscript and Font Size (2026)

Markdown small text has no native syntax: use the HTML small, sub and sup tags. Why span style and H~2~O fail silently, plus a full platform support table.

Tutorial

Markdown Collapsible Section: details, Dropdown and Toggle (2026)

Markdown collapsible sections use the HTML details and summary tags. The blank-line rule explained from the spec, plus dropdown, accordion and toggle syntax.