Markdown Table Generator
GFM (GitHub Flavored Markdown) tables use pipe characters to separate columns, a separator row with dashes to define the header, and optional colons in the separator row to control alignment. The format is supported on GitHub, GitLab, many static site generators, and most Markdown editors.
GFM Table Syntax
The minimum valid table needs a header row, a separator row, and at least one data row:
| Name | Role |
|------|------|
| Alice | Engineer |
| Bob | Designer |
The separator row must have at least three dashes per cell (---). More dashes are fine; they do not change behavior, only readability in source.
Column Alignment
Alignment is set with colons in the separator row:
| Left | Center | Right |
|:-----|:------:|------:|
| text | text | text |
| Syntax | Alignment |
|---|---|
:--- | Left (default) |
:---: | Center |
---: | Right |
Right alignment is most useful for numeric columns where you want digits to line up.
Pipe Formatting in Source
The pipes at the start and end of each row are optional in the spec, but most formatters and linters require them. You do not need to pad cells to align the pipes visually. These two tables render identically:
| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Short | A much longer cell value | x |
|Column 1|Column 2|Column 3|
|---|---|---|
|Short|A much longer cell value|x|
Prettier and similar formatters will pad the short version out to the aligned version on save.
What Markdown Tables Cannot Do
No merged cells
Every row must have exactly the same number of cells. There is no colspan or rowspan equivalent. If a cell is conceptually empty, use a space or leave it blank: | |.
No nested tables
A table cell cannot contain another table. Cells also cannot contain block-level elements like code fences, blockquotes, or lists. Inline formatting (bold, code, links) works inside cells.
No multiline cells
A cell cannot span multiple lines in source. If you need to put a lot of text in a cell, the table will be hard to read. The workaround is to keep cells short or switch to a different content structure.
HTML Tables as a Fallback
When GFM tables are not flexible enough, raw HTML works inside most Markdown documents:
<table>
<tr>
<th colspan="2">Merged header</th>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
</table>
This works on GitHub and in most static site generators. It does not work in environments that strip HTML for security reasons (some wikis, some Markdown preview tools).
Generating Tables from Data
If you have structured data and need to convert it to Markdown, a few approaches work well:
import pandas as pd
df = pd.read_csv("data.csv")
print(df.to_markdown(index=False))
// Node.js: basic TSV to Markdown table
const rows = tsvString.trim().split("\n").map(r => r.split("\t"));
const header = `| ${rows[0].join(" | ")} |`;
const sep = `| ${rows[0].map(() => "---").join(" | ")} |`;
const body = rows.slice(1).map(r => `| ${r.join(" | ")} |`).join("\n");
console.log([header, sep, body].join("\n"));
Keeping Source Tables Readable
For tables you edit by hand in source, a few habits help. Keep column content short (under 20 characters if possible). Use a Markdown formatter (Prettier with the prose-wrap option) so alignment is handled automatically. For tables that will be read mostly in rendered form and rarely edited, alignment in source matters less.
If you use VS Code, the Markdown Table extension can auto-format tables on save and lets you navigate cells with Tab the same way you would in a spreadsheet.