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 | |  | 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.
| Renderer | Tables |
|---|---|
| GitHub, GitLab, Gitea | Yes, GFM |
| CommonMark reference | No, renders as a paragraph |
| Pandoc | Yes with pipe_tables, plus three other table syntaxes |
| MultiMarkdown | Yes, plus colspan and multi-row headers |
| Markdown Extra | Yes |
| Obsidian, VS Code preview | Yes |
| Slack, Discord | No |
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.