Tables are the Markdown feature people look up most often, because the syntax is not obvious and the failure mode is silent: a mistake just leaves you with a block of pipes. Tables are an extension in GitHub Flavored Markdown (GFM) rather than part of core CommonMark, so they need a renderer that supports GFM.
The basic syntax
A table has a header row, a separator row, and any number of body rows. Columns are divided by pipes (|):
| Name | Role | Active |
|-------|--------|--------|
| Ada | Admin | Yes |
| Linus | Editor | No |
The separator row is required. Without it, nothing is rendered as a table. Each cell in the separator needs at least three hyphens in many renderers; the GFM spec itself allows fewer, but three is the safe choice. The outer pipes at the start and end of each line are optional in GFM, but including them makes tables easier to read and avoids edge cases.
Column alignment
Colons in the separator row set alignment:
| Left | Center | Right |
|:-----|:------:|------:|
| a | b | c |
:---aligns left (also the default):---:centres---:aligns right
Right alignment is useful for numbers, so digits line up.
You do not need to align the source
The raw text does not have to line up. This renders identically to the neat version:
|Name|Role|
|-|-|
|Ada|Admin|
Neat source is a courtesy to future editors, not a requirement. For wide tables, aligning the pipes by hand is tedious, so many editors have a "format table" command.
Putting a pipe inside a cell
A pipe character inside a cell would be read as a column divider. Escape it with a backslash:
| Command | Meaning |
|----------------|------------------|
| `a \| b` | a piped into b |
Formatting inside cells
Inline formatting works in cells: bold, italics, inline code, links and images. Block elements do not. A cell cannot contain a list, a heading or a code block in standard GFM.
Line breaks in cells
A cell must stay on one line of source. If you need a break inside a cell, many renderers accept an HTML <br> tag, but that depends on the renderer allowing raw HTML. Sanitising renderers may strip it. For long content, consider whether a list below the table would read better.
Rows with the wrong number of cells
GFM is forgiving here: excess cells in a row are ignored and missing cells are treated as empty. But the header row and the separator row must have the same number of cells, or the table is not recognised. This is the most common reason a table fails to render.
Troubleshooting a table that will not render
- Check for a blank line before the table. In some parsers the table must be separated from the preceding paragraph.
- Check the separator row. It must exist and match the header's column count.
- Check for unescaped pipes inside cells.
- Check the renderer. A CommonMark-only parser shows pipes as text. See Markdown flavors explained.
- Look at tab characters. Tabs mixed with spaces can break indentation-sensitive parsing.
Generating tables from CSV
If your data is already in a spreadsheet or CSV file, you do not have to retype it. Copy it into a table-formatting tool, or write a short script that joins each row with | and adds a separator row after the header.
Preview as you build
The quickest way to catch mistakes is to see the result. In Docento's Text & Markdown Editor, paste your table and switch to Preview; the editor renders GFM tables. If the preview shows pipes, one of the checks above will tell you why.
Takeaway
A Markdown table is a header, a separator row of hyphens and rows of cells divided by pipes. Escape literal pipes, keep cell contents to one line, make header and separator widths match, and preview before publishing.