Markdown Table Syntax: How Tables Work (and Break)
Two weekends ago I pasted the same nine-row table into seven different Markdown renderers: GitHub, VS Code's preview, Reddit, Discord, Slack, a static site generator, and my note-taking app. Then I logged what happened in a spreadsheet. (Yes, I made a spreadsheet about Markdown tables. No, I will not apologize.) Four rendered a clean table. Two printed my careful rows back as a paragraph of literal pipe characters. One rendered the header and abandoned the body entirely.
The interesting part: not one of the failures was a typo.
Markdown table syntax itself takes about two minutes to learn — it's two required lines and some optional colons, and I'll show you both. What takes slightly longer is the thing my experiment actually measured: why a perfectly correct table renders in one app and collapses in another, and how to write tables that survive the trip.
The two lines that make Markdown table syntax work
Here's a complete, working table:
| Tool | Runs locally | Price |
| ------ | ------ | ----- |
| Formatter | Yes | Free |
| Converter | Yes | Free |
Line one is the header row. Line two — the hyphens — is the delimiter row, and it does all the load-bearing work. It's the handshake that tells the renderer "everything above me is a header, everything below me is data." Delete it and you don't get a slightly broken table; you get no table at all, just a paragraph with pipes in it. In my seven-renderer test, a malformed delimiter row was the one failure I could reproduce on purpose, everywhere, every time.
Three things I verified about that row while building my test file:
- Each column needs at least one hyphen, so
|-|-|-|is technically valid. I checked. It works. It's also miserable to read, so give each column three or more. - The outer pipes at the start and end of every row are optional in most renderers. Keep them anyway — they cost four keystrokes and remove a whole category of edge cases around cells that start or end with awkward characters.
- Data rows can be ragged. A row with too few cells gets padded with empty ones, and extra cells are silently dropped. Silently! If a column of your data ever just vanishes, count your pipes before you question your sanity.
Alignment is the delimiter row's second job, and colons are the entire control surface:
| Left | Center | Right |
| :--- | :----: | ----: |
| a | b | c |
Colon on the left of the hyphens aligns that column left, colons on both sides center it, colon on the right aligns right. No colons means left-aligned by default. And that's everything — no column widths, no cell colors, no merged cells. Hold onto that list of missing features; it comes back at the end.
Why a correct table still breaks: tables aren't Markdown
Now the finding that reorganized my whole spreadsheet. Tables were never part of Markdown. The original 2004 Markdown had no table syntax at all, and CommonMark — the spec most modern renderers build on — deliberately leaves tables out of the core. Tables arrived later as an extension in GitHub Flavored Markdown (GFM), and every platform since has either adopted that extension, shipped its own dialect, or skipped tables entirely.
Think of it like a board game. CommonMark is the rulebook in the box: every table you sit down at plays those rules the same way. Tables are an expansion pack — hugely popular, sold separately, owned by most groups but not all. When your table won't render somewhere, you usually haven't played a card wrong; you've brought an expansion to a group that doesn't own it. Re-reading the rulebook won't fix that, because the rules you need aren't in it.
So the first debugging question isn't "what did I mistype?" It's "does this renderer support tables at all?" In my test, GitHub, VS Code's preview, Reddit, and my note-taking app all own the expansion — clean tables everywhere. Discord and Slack are base-game only: both printed my pipes as literal text, and no syntax variation I tried (and I tried several, increasingly desperate) changed the outcome. Nothing was wrong with the table. There was simply no table renderer on the other end.
The seventh case — the static site generator that rendered my header and dropped the body — turned out to be the one genuine bug in my own file: no blank line between the preceding paragraph and the table, so the header row got absorbed into the paragraph above it. One blank line fixed it. Cheapest fix of the weekend.
And my one wrong assumption, admitted for the record: I spent the first fifteen minutes of the experiment padding my source with spaces so the pipes lined up in tidy columns, convinced the alignment mattered. It doesn't. Every renderer that passed ignored the whitespace completely — the beautifully aligned source and the ragged one produced identical output. Pretty pipes are for humans reading the raw file, which is a fine reason in a README your teammates edit, but the renderer never sees them.
The portable-table checklist
After the test, this is the version I write every time — the table that renders everywhere tables render at all:
- Blank line above the table. The silent killer from my test. A table glued to the paragraph before it gets eaten.
- Keep the outer pipes. Optional in theory, free insurance in practice.
- Three-plus hyphens per column in the delimiter row, nothing in it but hyphens, colons, and pipes.
- Escape literal pipes inside cells as |. A cell containing code like
a || bwill splinter into phantom columns without it — this one bit me mid-experiment. - One source line per row. Cells can't hold paragraphs, lists, or code blocks. An inline
<br>gets you a line break inside a cell in most renderers, and that's as multi-line as it gets.
When a Markdown table is the wrong tool
Remember the missing features? If your data genuinely needs merged cells, more than five or six columns, or real multi-line content, a Markdown table will fight you the entire way. You have two honest options. Restructure the data — often the better answer, since a table nobody can read on a phone wasn't communicating anyway. Or drop an inline HTML <table> into the document, which most Markdown renderers pass straight through. If you go the HTML route, mind the characters that need escaping in markup — our HTML entities guide covers the five that actually matter.
And past a handful of rows, stop typing pipes by hand entirely. That's where the real typo-shaped failures breed — the ragged row, the unescaped pipe, the delimiter cell you forgot. If the data lives in a spreadsheet, export it as CSV (here's a refresher on how the CSV format works if the quoting rules are hazy) and paste it into the CSV to Markdown Table converter, which handles the delimiter row, the pipes, and the escaping for you. Sanity-check the result in the Markdown Previewer before you commit it. And for the Slacks and Discords of the world, where tables will never render, convert the finished document with the Markdown to HTML converter — or skip Markdown and generate an HTML table straight from the CSV for wherever HTML is welcome.
Conclusion
Final tally from the spreadsheet: seven renderers, four clean tables, two platforms that will never render one, one missing blank line, zero actual syntax errors. That's Markdown table syntax in practice — a header row, a delimiter row, alignment colons, and one honest question to ask before debugging anything: does this renderer own the tables expansion at all? Write the portable version, generate anything bigger than a few rows from CSV, and preview before you publish. What I'd test next: the same nine rows in mobile Markdown editors and chat apps' preview panes — my hypothesis is more pipe soup than anyone would like.
Try the tools
Frequently Asked Questions
How do you make a table in Markdown?
Write a header row with column names separated by pipes, then a delimiter row of hyphens beneath it (like | --- | --- |), then one line per data row. The delimiter row is required — without it, renderers treat the whole block as plain text.
Why is my Markdown table not rendering?
The three usual causes, in order: the platform doesn't support tables at all (Slack and Discord don't — no syntax fixes that), there's no blank line between the table and the paragraph above it, or the delimiter row is missing or malformed.
How do you align columns in a Markdown table?
With colons in the delimiter row: :--- aligns the column left, :---: centers it, and ---: aligns it right. Without colons, columns default to left alignment. There's no syntax for column widths or colors.
Can a Markdown table cell contain multiple lines or merged cells?
Not in standard GFM tables. Each row is one source line, and there's no merge syntax. An inline <br> tag gives you a line break inside a cell in most renderers; for genuine multi-line content or merged cells, use an HTML table instead.
Do the pipes in a Markdown table have to line up?
No. Renderers ignore the extra whitespace, so a ragged table and a beautifully aligned one produce identical output. Aligned pipes only help humans reading the raw file — useful in a shared README, invisible to the renderer.
CodeUtilityKit Team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.