Markdown Columns: 3 Ways to Build Multi-Column Layouts

September 11, 2026 · 9 min read

Markdown Columns: 3 Ways to Build Multi-Column Layouts

Markdown columns don't exist as a syntax. You can fake them three ways: a borderless table, raw HTML, or Pandoc fenced divs. Which one works depends on where the file renders. This post builds the same two-column block each way and tells you which survives on GitHub, in Obsidian, in a Pandoc PDF, and in our editor.

Why Markdown Has No Column Syntax

CommonMark and GitHub Flavored Markdown describe content, not layout. There's a syntax for headings, lists, and tables, but nothing that says "put this paragraph next to that one". The Stack Overflow question on two-column Markdown has a long list of competing answers, which is a sign that every option is a workaround.

That's not a flaw to fix. Markdown files get read in a text editor, a phone browser, a terminal, and a PDF, and a layout that looks right in one breaks in another. So the useful question isn't "what's the syntax" but "which workaround does my target renderer keep". The three below cover almost every case.

Method 1: A Table as a Column Grid

A GFM table is the most portable way to get two things side by side. Leave the header cells empty and the alignment row does the rest.

|   |   |
|---|---|
| **Good** | **Bad** |
| `const x = 1;` | `var x = 1;` |
| Short, named functions | One 400-line function |

That renders as a two-column grid with a thin (empty) header row. Every cell is inline content only. The GFM spec states that block-level elements cannot be inserted in a table, so a list, a code block, or a heading inside a cell breaks the table. You can squeeze in line breaks with <br /> and fake a bullet with , but a real list needs Method 2.

Two images in a row is the most common column request, and a table handles it well: | ![before](a.png) | ![after](b.png) | with a matching delimiter row. The Markdown image guide covers sizing those images once they sit side by side. For table alignment, column width, and escaping pipes inside cells, see the Markdown table guide; this post only uses tables as a layout hack.

Method 2: Raw HTML Columns

Where inline HTML is allowed, an HTML <table> gives you columns that can hold block content. The trick is the blank line: the CommonMark spec says an HTML block ends at a blank line, and Markdown after that blank line is parsed normally. So Markdown inside a <td> renders only when you surround it with blank lines.

<table>
<tr>
<td width="50%">

**Left column**

- A real list
- with real bullets

</td>
<td width="50%">

**Right column**

```js
const works = true;
```

</td>
</tr>
</table>

On GitHub, that renders as two columns with a bulleted list on the left and a highlighted code block on the right. GitHub's sanitizer keeps table, tr, td, div, and the align, width, and height attributes, but strips style, class, and id. That's why the flexbox version people paste from CSS tutorials fails on GitHub: <div style="display:flex"> loses its style attribute and the divs stack vertically. The GitHub Markdown cheat sheet lists what else survives.

On your own site, where nothing is stripped, a flex container is the cleaner choice:

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

Left text.

</div>
<div style="flex:1">

Right text.

</div>
</div>

We prefer the HTML table on GitHub and flex everywhere else. The Markdown vs HTML comparison explains where raw HTML gets stripped entirely (Slack, Discord, and most chat apps), which rules out this method there.

Method 3: Pandoc Fenced Divs

If you convert Markdown with Pandoc, fenced divs are the native answer. A block wrapped in ::: lines becomes a <div> in HTML and an environment in LaTeX, and Pandoc has a built-in columns layout for slides.

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

The Pandoc manual documents this in its slide-show section, with extra alignment attributes for Beamer and a note that column widths don't yet apply in PowerPoint. For a normal HTML or PDF document, the divs come through with their classes but nothing positions them.

The R Markdown Cookbook's recipe 5.8 puts it plainly: Pandoc's Markdown supports multi-column layout for slides but not other document types. Its fix is a display: flex rule on the outer div for HTML output, and a LaTeX environment for PDF.

One nice side effect: the Obsidian Multi-Column Markdown plugin accepts the same ::::: {.columns} syntax, so a file written this way works in both places.

How Do You Make Two Columns in Obsidian?

Obsidian's formatting reference has no column syntax, so the answer is a plugin. Multi-Column Markdown by ckRobinson adds column regions in Live Preview and Reading view. Its latest release is 0.9.1 from January 2024, with the last commit in May 2024:

--- start-multi-column: ID_example
```column-settings
Number of Columns: 2
```

Left column text.

--- column-break ---

Right column text.

--- end-multi-column

It also accepts the Pandoc form from Method 3. Two things to know before you commit to it. The plugin has had no release since January 2024 and no commits since May 2024, and the file shows the raw --- lines in any app other than Obsidian. If your notes leave Obsidian often, a table is the safer choice.

Try Markdown Columns in the Editor

The sample below has all three methods. In our editor, the table renders as a grid and the HTML table renders with Markdown inside the cells. The Pandoc divs show as plain text with the ::: lines visible, which is exactly what a CommonMark renderer does with them.

Method 1: table

Left Right
Short and portable Inline content only

Method 2: HTML table

  • Real list
  • Real bullets

Bold and italic text

Method 3: Pandoc divs (plain text here)

:::: {.columns}
::: {.column width='50%'}
Only Pandoc lays this out.
:::
::::

64 words393 characters32 lines
Markdown

Convert the result with the Markdown to HTML tool to see the exact HTML each method produces.

Which Markdown Column Method Works Where?

TargetTable (Method 1)HTML tableHTML flex divPandoc divs
GitHub README, issuesYesYesNo (style stripped)No (shows :::)
GitLabYesYesNoNo
ObsidianYesYesNot testedWith the plugin
Pandoc to HTMLYesYesYesYes, needs CSS
Pandoc to PDF (LaTeX)YesNoNoYes, needs LaTeX
Pandoc slides (Beamer, pptx)YesNoNoYes, native
Our editorYesYesYesNo

Read "Yes" as "renders side by side on a wide screen". On a phone, none of them reflow: a table with two long text cells becomes a narrow, hard-to-read strip, and an HTML table does the same. Columns are a desktop feature. Keep the text in each column short, or accept that mobile readers see a squeeze.

Common Markdown Column Mistakes

Markdown inside HTML with no blank lines. <td>**bold**</td> on one line prints the asterisks on GitHub because the whole line is one HTML block. Put a blank line after <td> and before </td>.

A list inside a GFM table cell. | - item one<br />- item two | doesn't make a list; it's text with a line break. Switch to an HTML table for real list markup.

Splitting one long list into two columns. There's no syntax for it. Either build a two-cell table with <br /> separated items, or use an HTML table with a <ul> in each <td>.

Markdown Columns FAQ

Pick the method by target. Use a table for anything that must render everywhere, an HTML table for GitHub and docs sites, and fenced divs when Pandoc is doing the conversion. Whichever way you build markdown columns, paste the block into the editor before you commit it, and check the mobile view once so the layout doesn't surprise you.