Markdown Cheatsheet

Tables

Use this Markdown reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Basic Syntax

Tables are a GFM extension. They are not in CommonMark, so a strict CommonMark parser renders the source lines as a paragraph full of pipe characters.

A table is a header row, a delimiter row, then body rows. The delimiter row is what makes it a table.

| Header A | Header B |
|----------|----------|
| cell 1   | cell 2   |
| cell 3   | cell 4   |

The delimiter row needs at least one - per column. Leading and trailing pipes are optional, so this is the same table:

Header A | Header B
--- | ---
cell 1 | cell 2
cell 3 | cell 4

Column widths in the source do not have to line up. The following renders identically to the aligned version above, which is why a formatter reflowing your tables changes nothing about the output.

| Header A | Header B |
|-|-|
| a | b |
| a much longer cell | b |

Aligning the source is purely for the human reading the raw file. prettier and most editor plugins will do it for you.

Alignment

A colon in the delimiter row sets the column's alignment.

| Left | Center | Right | Default |
|:-----|:------:|------:|---------|
| a    | b      | c     | d       |
| aa   | bb     | cc    | dd      |
  • :--- left aligned
  • :---: centered
  • ---: right aligned
  • --- renderer default, which is left in practice

The colons must be in the delimiter row, on the outer edges of the dashes. :-: works, a single - between colons is enough. Right alignment is the right choice for numeric columns.

| Item      | Qty |  Price |
|:----------|----:|-------:|
| Widget    |   3 |  12.00 |
| Gadget    |  12 | 199.50 |

Escaping Pipes

A literal | inside a cell ends the cell, so it must be escaped with a backslash. This applies even inside a code span, because the table is split into cells before inline parsing.

| Command | Meaning |
|---------|---------|
| `a \| b` | pipe a into b |
| `x \|\| y` | logical or |

For anything with many pipes, such as a shell pipeline or a regex alternation, the HTML entity is an alternative that some people find more readable:

| Pipeline |
|----------|
| `ls | wc -l` |

Neither is pretty. When a table cell needs a long pipeline, consider a fenced code block below the table instead.

Column Count Mismatches

The header row fixes the column count. Everything else is adjusted to it.

  • A body row with too few cells is padded with empty cells.
  • A body row with too many cells has the extras silently dropped.
  • The delimiter row must match the header row's count exactly, or the whole thing is not a table.
| A | B | C |
|---|---|---|
| 1 | 2 |         <- becomes 1, 2, empty
| 1 | 2 | 3 | 4 | <- the 4 is discarded

That last rule is the usual cause of "my table renders as a paragraph": the delimiter row has a different number of columns than the header.

What Cannot Go in a Cell

GFM table cells hold inline content only. No block elements at all.

Allowed: bold, italic, code spans, strikethrough, links, images, autolinks, and HTML inline tags where raw HTML is permitted.

Not allowed: fenced code blocks, lists, blockquotes, headings, paragraphs, or a nested table.

| Works | Does not work |
|-------|---------------|
| **bold** and `code` | a fenced code block |
| [a link](https://example.com) | a bullet list |
| ![img](./i.png) | a nested table |

Workarounds people use:

  • A <br> for a line break inside a cell, where raw HTML is allowed. GitHub permits it.
  • <ul><li> HTML for a list inside a cell. Verbose, and stripped by strict sanitizers.
  • Restructure: put the table's detail in a numbered section below and reference it.
| Step | Detail |
|------|--------|
| One  | first line<br>second line |

Empty Cells and Empty Tables

An empty cell is just nothing between two pipes. A visible placeholder reads better than blank space.

| Option | Default | Notes |
|--------|---------|-------|
| `-v`   |         | verbose |
| `-n`   | 10      | — |

A table needs at least a header and a delimiter row. A header-only table is valid and renders as a table with no body. There is no syntax for a table without a header row: the workaround is an empty header row, which every renderer accepts but which produces an empty visible header band.

|  |  |
|--|--|
| a | 1 |
| b | 2 |

Portability

Tables are the extension most likely to break when a file moves between tools.

RendererTables
GitHub, GitLab, GiteaYes, GFM
CommonMark referenceNo, renders as a paragraph
PandocYes with pipe_tables, plus three other table syntaxes
MultiMarkdownYes, plus colspan and multi-row headers
Markdown ExtraYes
Obsidian, VS Code previewYes
Slack, DiscordNo

Pandoc and MultiMarkdown add features GFM lacks, notably cell spanning and captions. Using them makes the file non-portable in the other direction, so for anything published to a repository, stay on plain GFM pipe tables.

If a table needs merged cells, a caption, or block content in a cell, it has outgrown Markdown. Write it as an HTML table, or split it into sections.