How to Create Tables in Markdown

Build a Markdown table with pipes (|) separating columns and a delimiter row of dashes under the header: | Header | Header | on line one, |---|---| on line two, then one row per line. The delimiter row is mandatory — without it, nothing renders as a table.

Platform Support

GitHubsupportedGitLabsupportedObsidiansupportedDiscordnot supportedSlacknot supportedNotionsupported

Tables are a GFM extension, not core Markdown, but support is near-universal outside of chat apps. The delimiter row does double duty: it marks the header boundary and sets column alignment. A colon on the left of the dashes (:---) left-aligns the column, colons on both sides (:---:) center it, and a colon on the right (---:) right-aligns it — right alignment is the right call for numeric columns. Leading and trailing pipes on each row are optional in GFM, but including them makes the source easier to scan and is required by some stricter parsers.

The most common table bug is an unescaped pipe inside a cell. Any literal | in cell content — say, documenting a shell command like grep foo | sort — splits the cell in two. Escape it as \| in plain text. Inside inline code within a cell the backslash escape still applies in GFM (`a \| b`), or you can use the HTML entity &#124; when the backslash is not honored. Cells can contain inline formatting (bold, links, inline code, images) but not block elements: no lists, no multi-line paragraphs, no code fences. The standard workaround for a line break inside a cell is the <br> tag.

Column widths in the source do not need to line up — | a | longer text | renders identically to a perfectly padded table — but aligned source is vastly easier to edit and review in diffs. A formatter (or our table generator) keeps the pipes aligned for you. Each row should have the same number of cells as the header; extra cells are dropped and missing ones render empty, both silently, which makes mismatches easy to miss.

Markdown tables deliberately stay simple: there is no syntax for merged cells, row spans, column widths, or captions. When you genuinely need those, drop down to a raw HTML table (where the platform allows it) or restructure the data — often a heading-plus-list layout communicates merged-cell data better than a table. Keep tables for genuinely tabular data; for key-value pairs, a two-column table works but a definition-style list is often more readable on mobile.

Examples

Table
Markdown
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1   | Cell 2   | Cell 3   |
| Cell 4   | Cell 5   | Cell 6   |
Output
Header 1 Header 2 Header 3
Cell 1 Cell 2 Cell 3
Cell 4 Cell 5 Cell 6

Create tables using pipes and dashes.

Table Alignment
Markdown
| Left | Center | Right |
|:-----|:------:|------:|
| L    | C      | R     |
Output
Left Center Right
L C R

Align table columns using colons.

Escaped pipe inside a cell
Markdown
| Command | Description |
|---|---|
| `grep foo \| sort` | Filter then sort |
Output
Command Description
grep foo | sort Filter then sort

A raw | inside a cell splits the column — escape it with a backslash.

Line break inside a cell
Markdown
| Step | Notes |
|---|---|
| Deploy | Run the script<br>then verify logs |
Output
Step Notes
Deploy Run the script
then verify logs

Cells cannot hold multiple lines of Markdown; use <br> where HTML is allowed.

Right-aligned numbers
Markdown
| Item | Price |
|:-----|------:|
| Coffee | $4.50 |
| Sandwich | $12.00 |
Output
Item Price
Coffee $4.50
Sandwich $12.00

Common Mistakes

Wrong
A header row with no |---|---| line under it
Right
| H1 | H2 |
|----|----|
| a  | b  |

The delimiter row of dashes is required. Without it the "table" renders as a plain paragraph of pipes and text.

Wrong
| uses grep foo | sort |
Right
| uses grep foo \| sort |

An unescaped pipe inside a cell starts a new column. Escape literal pipes with a backslash (or &#124;).

Wrong
Rows with different cell counts than the header
Right
Give every row exactly as many cells as the header

Extra cells are silently dropped and missing cells render empty — the table looks subtly wrong with no error.

Platform Notes

GitHub

Full GFM table support with alignment colons. Inline formatting works in cells; block elements and merged cells do not — use HTML tables for those.

Discord

No table support in messages. The common workaround is a code block with manually aligned columns.

Slack

No Markdown table support. Paste tables as code blocks or use a Canvas/snippet instead.

Obsidian

Full table support plus a visual table editor (right-click a table) since v1.5. Alignment colons work as in GFM.

Frequently Asked Questions

How do I make a table in Markdown?

Write a header row with cells separated by pipes, then a delimiter row of dashes (|---|---|), then one data row per line: | Name | Age | / |---|---| / | Ana | 31 |.

How do I align columns in a Markdown table?

Add colons to the delimiter row: :--- for left, :---: for center, ---: for right. Alignment applies to the whole column, header included.

How do I put a pipe character inside a table cell?

Escape it with a backslash (\|). If the backslash is not honored in your renderer (for example inside some code spans), use the HTML entity &#124;.

Can I merge cells in a Markdown table?

Not with Markdown syntax — GFM tables have no colspan/rowspan. Use a raw HTML <table> where the platform allows it, or restructure the data.

Can I put a list or multiple lines inside a table cell?

No block elements are allowed in cells. For simple line breaks use <br>; for real lists, switch to an HTML table or rethink the layout.

Related Syntax

Related Tools