Why tables are the trickiest part of Markdown
- A table needs three parts: a header row, a delimiter row of dashes, and data rows.
- Colons in the delimiter row set the alignment of a whole column, never of one cell.
- Cells take inline formatting only. No line breaks, no lists, no code blocks.
- A real pipe inside a cell has to be escaped as
\|, or it splits the cell in two.
Tables were bolted on later
Most Markdown syntax is forgiving. Forget a space and the renderer usually shrugs and fixes it for you. Tables are different. They were never part of the original 2004 Markdown, and the pipe syntax that GitHub Flavored Markdown standardized is strict about structure. Lose one delimiter row and your data renders as a single garbled paragraph, with no error message to explain why.
Tables are also the element whose source looks least like its output. A bold word still looks bold-ish written as **bold**. Table source is a thicket of pipes and dashes that only becomes a grid after rendering.
That gap is where a live preview earns its keep. Paste a draft into the editor and you watch the grid form, or fail to form, as you type each row.
Is a table even the right shape?
Worth asking before you build one. Tables are brilliant for genuinely tabular data and awful for everything else:
- Good fits - Feature comparisons, option and description pairs, pricing tiers, API parameters.
- Poor fits - Long prose in cells (use headings and paragraphs), hierarchies (use nested lists), anything that needs merged cells.
- Hard limits - Markdown has no rowspan and no colspan, and more than five or six columns is unreadable on a phone.
When the data does fit, nothing communicates it more clearly. And the syntax takes five minutes to learn properly. Let's do that.
Basic table syntax
A Markdown table needs exactly three ingredients: a header row, a delimiter row of dashes, and one or more data rows. Pipes (|) separate the columns:
| Name | Role | Location |
| ------- | --------- | -------- |
| Amelia | Designer | Taipei |
| Ben | Developer | Tainan |
| Chihiro | Writer | Taichung |
Which renders as:
| Name | Role | Location |
|---|---|---|
| Amelia | Designer | Taipei |
| Ben | Developer | Tainan |
| Chihiro | Writer | Taichung |
The delimiter row is the whole trick
The delimiter row is the line of dashes sitting directly under the header. It is what tells the parser "this is a table". It is not decoration. Without it there is no table at all.
Each column wants at least three dashes (---), though most renderers accept fewer. The count of dashes does not set the column width. The renderer sizes each column to fit its content.
Your pipes do not have to line up
Cell widths in the source are entirely free. This renders identically to the table above:
| Name | Role | Location |
| --- | --- | --- |
| Amelia | Designer | Taipei |
Padded, aligned source is purely for the humans reading the raw file. It is a kindness worth extending in files your teammates will edit, and a waste of time in a quick comment. If you like tidy source but not the fiddling, the table generator pads the pipes for you.
Column alignment with colons
Every column is left-aligned by default. Colons in the delimiter row change that, one column at a time:
:---- Left-aligned (explicit, same as the default):---:- Center-aligned---:- Right-aligned
| Item | Quantity | Price |
| :------------ | :------: | ----: |
| Notebook | 3 | $4.50 |
| Fountain pen | 1 | $28.00 |
| Ink cartridge | 12 | $0.75 |
Renders as:
| Item | Quantity | Price |
|---|---|---|
| Notebook | 3 | $4.50 |
| Fountain pen | 1 | $28.00 |
| Ink cartridge | 12 | $0.75 |
Which column gets which alignment
Alignment applies to the whole column, header cell included. You cannot align a single cell on its own. The conventions are simple, and they do a lot for how professional a table reads:
- Right - Numbers, money and dates. The digits line up, so the eye can compare them down the column.
- Center - Short status values: Yes, No, Beta, a tick mark.
- Left - Everything else, especially names and descriptions.
Building a table from scratch? The Markdown table generator has an alignment control per column, so you can set this with a dropdown instead of counting colons.
What formatting works inside a cell
Cells accept inline Markdown - Anything that lives inside a single line of text:
| Feature | Status | Docs |
| --------- | ------------------ | ----------------------------- |
| **Export**| Done | [Guide](https://example.com) |
| *Sync* | ~~Cancelled~~ | `sync --help` |
Bold, italic, strikethrough, inline code and links all render normally inside a cell.
What does not fit in a cell
Anything Markdown treats as a block element:
- Line breaks - You cannot press Enter inside a cell, because a newline starts the next row. The workaround is the HTML tag
<br>. WritingFirst line<br>Second lineproduces two lines. This works on GitHub and most renderers, but not in every tool. - Lists -
- iteminside a cell renders as literal text, dash and all. If you truly need one, fake it with<br>between items (• one<br>• two). - Headings, blockquotes, code blocks - All block-level, all unavailable. Multi-line code in a cell is a strong sign it deserves its own fenced code block outside the table.
The one-line rule
Here is the rule of thumb. If the content fits naturally on one line, it works in a cell. If it needs vertical space, it does not belong in a Markdown table. Content with real internal structure usually wants a nested list or a section of its own instead.
Escaping pipes, wide tables, and readable source
Escaping a literal pipe
The pipe character defines column boundaries, so a real | inside a cell splits that cell in two. This bites whenever you document shell commands, regular expressions or type unions.
Escape it with a backslash. Write \| and the renderer prints a plain pipe, so a cell documenting grep \| sort keeps its columns intact. On GitHub the backslash works inside inline code spans too. If some other renderer disagrees, the HTML entity | is the universally safe fallback.
Tip: Backticks do not protect a pipe. The table parser splits the row before it looks at inline code, so `a | b` breaks the columns just like a bare pipe. Escape it inside the code span too.
Taming a wide table
Wide tables are the other recurring headache. Eight columns of prose are painful to edit as source and unreadable on a phone, where the table either overflows or shrinks to nothing. Before you fight it, try reshaping it:
- Split it - One wide table becomes two narrow ones.
- Move a column out - The wordy column becomes paragraphs below the table.
- Transpose it - Many columns become many rows. Rows are cheap in Markdown; columns are expensive.
A rough rule: more than five columns, or any cell over a dozen words, and the data is telling you it wants a different shape.
Let a tool write the pipes
For anything big or fiddly, stop typing pipes by hand. Our table generator gives you a spreadsheet-style grid and emits clean Markdown from it.
Already have the data somewhere else? Paste it straight out of Excel, Google Sheets or an HTML page into the table converter and it comes back as pipes. Write the content first, generate the syntax second.
Pretty source is optional
A ragged table with uneven pipes renders exactly like a hand-aligned one. Align the source when the file lives in a repository and teammates read raw diffs. Skip it for a one-off comment.
If you enjoy tidy sources, let a formatter or generator do the padding. Realigning by hand after every edit is how people learn to hate tables.
Common table errors and how to fix them
When a table refuses to render, it is almost always one of five things.
The five usual suspects
- Missing or malformed delimiter row. The number one cause. If the dashes are gone, mangled by autocorrect (
-–-with a stray en dash), or separated from the header by a blank line, the whole block prints as plain text. - Wrong column count in the delimiter row. It needs at least as many columns as the header. Give it three header columns and two delimiter columns and strict parsers refuse to build the table. GitHub's parser is one of them. Count your pipes.
- Uneven pipes in data rows. Short rows get padded with empty cells, and extra cells are dropped silently. The table renders, but values land in the wrong columns. If a value looks like it moved one column left, hunt for an unescaped
|earlier in that row. - No blank line before the table. A table pressed against the paragraph above it can be swallowed by that paragraph. Give it one blank line above and one below.
- Confusion about outer pipes. Leading and trailing pipes are optional in GFM.
Name | Roleworks as well as| Name | Role |. Keeping them is still the better habit: row boundaries stay obvious, the table survives a paste into stricter tools, and a few older renderers require them. Either way, be consistent within one table.
Watch out: Word processors and chat apps love to "fix" three dashes into one long dash. If you drafted the table somewhere else and pasted it in, retype the delimiter row before you debug anything else.
Broken, then fixed
Here is the top offender twice over. The first block renders as one line of text; the second renders as a grid:
Broken:
| Name | Role |
| Amelia | Designer |
Fixed:
| Name | Role |
| ------- | --------- |
| Amelia | Designer |
Three things to take from that pair:
- What was wrong - No delimiter row, so the parser never saw a table at all.
- What changed - One line of dashes and pipes, directly under the header, with no blank line between them.
- How to spot it - The output still shows your pipe characters. Visible pipes always mean the table was never built.
Debug any table in a minute
Paste it into the live-preview editor, delete rows until it renders, then add them back one at a time. The row that breaks it is the row with the problem, and it is usually a pipe.
If the table renders here but not where you published it, the problem is the platform, not the syntax. The compatibility notes in our cheat sheet say which tools support tables at all.
Support data verified
Frequently Asked Questions
Can I merge cells in a Markdown table?
No - Markdown tables have no rowspan or colspan. If your data genuinely needs merged cells, either restructure it into multiple simple tables or drop down to a raw HTML <table>, which most Markdown renderers (including GitHub's) will display.
How do I put a line break inside a table cell?
Use the HTML tag <br> where you want the break: First<br>Second. Pressing Enter won't work, because a newline ends the table row. Note that a few strict renderers strip HTML, in which case there is no way to break lines in a cell.
Do the pipes have to line up vertically?
No. Alignment of the raw source is purely cosmetic - | a | b | and a perfectly padded version render identically. Align the source only when humans will read the raw file, and ideally let a formatter or generator do it for you.
Why does my table render as plain text?
Check three things in order: the delimiter row of dashes exists directly under the header (no blank line between), it has at least as many columns as the header, and there's a blank line separating the table from the paragraph above it. One of those is nearly always the culprit.
Do Markdown tables work everywhere?
They're an extended-syntax feature, so no. GitHub, GitLab, Reddit, Obsidian and most modern tools support them; Discord and some minimal renderers don't. See the compatibility notes in our cheat sheet for the platform-by-platform picture.
Keep learning
Try the Editor
Try the Editor