Choosing How to Represent Tables in Markdown: Pipe Tables vs. Raw HTML vs. Lists
Core Markdown has no table syntax, so the real decision starts with your renderer's dialect. A practical guide to choosing between GFM pipe tables, raw HTML, and lists — with a probe-based validation approach.
29 Jul 2025, 05:48 UTC

You have data to put in a Markdown document, and the first surprise is that core Markdown has no table syntax at all. The original syntax and the CommonMark spec simply omit tables; what most people call a "Markdown table" is the GitHub Flavored Markdown (GFM) pipe-table extension. That single fact drives the whole decision: before choosing a syntax, you must know which dialect your renderer speaks. The useful takeaway: use pipe tables for small, flat data on GFM-compatible platforms, switch to embedded HTML when you need spans or multi-line cells, and reconsider whether a table is even the right shape for the content.
The decision and its constraints
Three constraints bind this choice, in order of importance:
- Renderer dialect. A CommonMark-strict parser (for example, markdown-it with default settings) renders pipe-table source as literal text with pipe characters. GFM-mode parsers (GitHub itself, Pandoc with
-f gfm, markdown-it with tables enabled, most static site generators) render them as real tables. If you don't control the renderer, portability argues against pipe tables. - Data shape. Pipe tables express only single-line cells with inline formatting. Row spans, column spans, multi-paragraph cells, and nested lists are impossible in the syntax.
- Reading context. Wide tables render poorly on narrow screens. If the audience reads on mobile, a list may serve better than a six-column table.
Comparing the supported options
| Option | Renderer support | Expressiveness | Authoring cost | Main risk |
|---|---|---|---|---|
| GFM pipe table | GFM-mode parsers only | Single-line cells, inline formatting, column alignment | Low; readable in source | Renders as literal pipes on CommonMark-strict platforms |
Raw HTML <table> | Most renderers pass HTML through, but sanitizers may strip it | Full HTML: spans, multi-line cells, nested content | High; verbose, easy to break | Sanitizer silently removes elements, breaking layout |
| Lists or headings | Universal (core Markdown) | Anything, but no grid | Low | Loses at-a-glance comparison for genuinely tabular data |
Trade-offs in practice
Pipe tables are the default choice when the data is genuinely tabular and small: a handful of columns, short cell text, one line per cell. They stay readable in the raw source, which matters for diffs and code review. The syntax requires a header row, a delimiter row of dashes, and body rows whose column count matches the header — mismatched columns produce parser-specific behavior, so don't rely on it.
Alignment is controlled by colons in the delimiter row: :--- left, ---: right, :---: center. Note that alignment is presentational only; it carries no semantic or accessibility meaning for screen readers.
The classic breakage point is a pipe character inside cell content, especially inside inline code spans (common when documenting CLI flags or regexes). Escape it as \| or use the HTML entity |:
| Pattern | Meaning |
|:--------------|---------------------:|
| `a \| b` | alternation |
| `|` literal | the pipe character |Raw HTML tables are the escape hatch for anything pipe tables cannot express: merged cells, multi-paragraph cells, embedded lists. The cost is real: the source becomes verbose, and any sanitizer in the pipeline (comment systems, CMS rendering, some email pipelines) may strip or escape the markup. If you go this route, verify the deployment pipeline's allowlist includes table, thead, tbody, tr, th, and td.
Lists are underrated. If each "row" has more than a sentence or two of content, or the data isn't actually a grid (a changelog, a FAQ, a feature list), a definition-style list under headings is more portable, more readable on mobile, and friendlier to screen readers than a cramped table.
A concrete validation approach
Delimiter-row quirks and escaping edge cases differ subtly between implementations, so the reliable check is to render a probe document through the exact production renderer and inspect the HTML output. Create a file table-probe.md:
| Left | Center | Right |
|:-----|:------:|------:|
| a \| b | `x \| y` | z |Render it with your production toolchain. For example, with Pandoc in GFM mode (run in a terminal; no special permissions needed; table-probe.md is your probe file):
pandoc -f gfm -t html table-probe.mdCheck the output for three things: the presence of <th> and <td> elements (confirming the table was parsed at all), align attributes or style classes reflecting the three alignment styles, and the escaped pipe appearing as a literal | inside the cell rather than splitting it into an extra column. If the output shows the raw pipe characters as text, your renderer is not in GFM mode — for markdown-it that means calling .enable('table'); for other tools, check their dialect configuration.
One risk to note: this validates parsing, not presentation. Long unbroken strings in cells (URLs, commit hashes) can still overflow narrow layouts. Open the rendered page at your narrowest target viewport and confirm the table either fits or gets horizontal scrolling; if it overflows, a CSS rule such as table-layout: fixed with word-break: break-word on cells is the usual fix.
Limitations
None of this is portable in the way core Markdown is. A document full of pipe tables authored for GitHub will degrade to literal pipe text on a CommonMark-strict platform, and raw HTML tables may vanish entirely behind a sanitizer. If the document must render acceptably everywhere, the conservative choice is to avoid tables and restructure the content as lists. When tables are justified, the decision rule is short: confirm the renderer's dialect first, use pipe tables for flat data, HTML for structural complexity, and validate with a rendered probe rather than trusting the source to look right.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.