← Blog Β· May 23, 2026 Β· dev, markdown

Markdown Tables: When to Hand-Write vs Use a Generator

Hand-write a Markdown table if it has under 4 columns and under 8 rows β€” anything bigger and you waste more time aligning pipes than writing content. The threshold is when the widest cell in column N changes and you have to re-pad every other row to match. Generators do this in milliseconds. Humans do it in minutes.

The minimal syntax

A Markdown table is two lines minimum: a header row and a separator row. Both use the| character as a column delimiter. The separator row uses - and optional : for alignment.

| Name  | Role     | Years |
| ----- | -------- | -----:|
| Alice | Engineer |     7 |
| Bob   | Designer |     3 |

Renders as a 3-column table with the last column right-aligned (note the : on the right). The leading and trailing | on each row are optional in GitHub Flavored Markdown but required for portability β€” write them.

Alignment, in 4 characters

SeparatorAlignment
---Default (left in most renderers)
:---Left
:---:Center
---:Right

That is the entire alignment spec. There is no justify, no per-cell alignment, no vertical alignment. If you need more, you are not writing Markdown β€” you are writing HTML.

Hand-writing is fine when the table is small

Three columns, five rows. You can eyeball it. You don't need a tool. The cost of opening a generator exceeds the cost of typing the pipes. Most engineering documentation tables fall in this range β€” release notes, API parameter lists, decision tables.

| Method | Path           | Auth |
| ------ | -------------- | ---- |
| GET    | /users         | Yes  |
| POST   | /users         | Yes  |
| GET    | /users/:id     | Yes  |
| DELETE | /users/:id     | Admin|

Twenty seconds to type. Aligned by eye. Done. Don't pull out a generator for this.

Generators win past these thresholds

  1. 5+ columns. Column widths interact unpredictably; re-padding cascades.
  2. 10+ rows. Any cell width change forces a global re-align.
  3. Data already exists in CSV, JSON, or a spreadsheet. Conversion is a one-shot task.
  4. Cells contain Markdown (links, inline code). Counting display width manually is error-prone.
  5. You will edit the table again. The second edit costs as much as the first if you hand-aligned.

Paste CSV or hand-write rows in our Markdown table generatorβ€” it auto-pads, supports per-column alignment, and outputs portable GFM syntax.

The portability matrix

RendererTables supported?Alignment?
GitHub Flavored MarkdownYesYes
GitLabYesYes
CommonMark (strict)No β€” tables are an extensionβ€”
Pandoc (default)Yes (4 table syntaxes!)Yes
NotionImports as a database, not a tableN/A
DiscordNoNo

Strict CommonMark does not include tables. Every renderer that supports them does so as an extension. The most universal subset is GitHub Flavored Markdown (GFM) β€” write tables for GFM and they work on GitHub, GitLab, Bitbucket, most static site generators, and most wikis.

Five gotchas that bite hand-writers

  1. Pipes inside cells. A literal | ends a cell. Escape it as\| or wrap the cell in backticks: `a|b`.
  2. Newlines inside cells. Not allowed in Markdown tables. Use <br>for a visual line break β€” renderers vary on whether they respect it.
  3. Empty cells. Two adjacent pipes (||) render as an empty cell. Leave a space inside (| |) for readability.
  4. Different column counts per row. The header sets the column count. Excess cells in body rows are dropped silently in GitHub.
  5. Indented tables. Indent a table 4 spaces and most renderers treat it as a code block. Tables must start at column 0.

Generating from CSV β€” the 3-line script

// CSV in β†’ Markdown table out
function csvToMd(csv: string): string {
  const rows = csv.trim().split('\n').map(r => r.split(','));
  const head = '| ' + rows[0].join(' | ') + ' |';
  const sep  = '| ' + rows[0].map(() => '---').join(' | ') + ' |';
  const body = rows.slice(1).map(r => '| ' + r.join(' | ') + ' |').join('\n');
  return [head, sep, body].join('\n');
}

Skips alignment and width-padding. Renders correctly. Good enough for 90% of cases β€” for the other 10%, our table generator does width-padded output and per-column alignment.

When to skip Markdown tables entirely

If you need merged cells, nested tables, or rich formatting inside cells β€” write HTML. Markdown is a plain-text format with a 90% coverage of common cases. The 10% it doesn't cover, it doesn't cover. Don't fight it.

Tools

← All blog posts