Markdown table generated from CSV in FormatArc CSV to Markdown converterMarkdown table generated from CSV in FormatArc CSV to Markdown converter
Published: 2026-04-27Updated: 2026-06-11

GitHub Markdown Table Syntax: Pipes, Hyphens & Alignment

Create GitHub Markdown tables with pipes, a hyphen header separator, and colon alignment. Copy-paste examples, escaping pipes, and a free CSV-to-Markdown generator.

Quick answer

Tables in Markdown use pipe characters | and hyphens -. Nothing else required.

| Name | Email | Role |
| --- | --- | --- |
| Mika | mika@example.com | admin |
| Noah | noah@example.com | viewer |

If typing pipes by hand is not your idea of a good time, paste CSV into CSV to Markdown and get a formatted table instantly. The rest of this article walks through the syntax in detail.

Basic syntax — pipes and hyphens

A Markdown table has three parts:

  1. Header row — column names separated by pipes |
  2. Separator row — hyphens - (conventionally three per column), separating the header from data
  3. Data rows — cell values separated by pipes
| Item | Value |
| --- | --- |
| CPU | Apple M4 |
| RAM | 16 GB |

Leading and trailing pipes are optional but recommended for readability. Column widths do not need to be aligned in the source; the renderer handles that.

Pipe and separator row anatomy

The pipe character | separates columns. The separator row — also called the header separator or dashes row — is built from hyphens - (commonly called dashes) and tells the renderer where the header ends and the data begins.

Row What it does Required?
Header row Names each column, written between pipes Yes
Separator row Hyphens (---) divide header from data and hold the alignment colons Yes
Data rows Cell values between pipes One or more

A few rules worth knowing about pipes and dashes:

  • Three dashes per column (---) is the convention, but not a parser rule. The GFM spec sets no minimum, and -- or even a single - renders as a table in GFM renderers (verified with marked 18.0.1 and remark-gfm 4.0.1). Stick with three dashes for readability, not because fewer would fail
  • What actually breaks a table is a separator row whose column count differs from the header row. The GFM spec is explicit: if the counts don't match, the table is simply not recognized
  • Pipes at the row start and end are optional, but recommended for readability. | A | B | and A | B both render the same
  • Alignment colons (:---, :---:, ---:) only go in the separator row, never in data rows
  • The header row is mandatory in GFM. CommonMark's core spec has no tables at all, so headerless tables exist only in custom extensions

If a renderer ignores your table, check the column counts first: a separator row that doesn't match the header row's column count prevents table recognition entirely. The other common cause is a missing blank line before the table — the dash count is almost never the problem.

Column alignment — left, center, right

Add colons : to the separator row to control alignment:

Syntax Alignment
:--- Left (default)
:---: Center
---: Right
| Product | Qty | Price |
| :--- | :---: | ---: |
| Apples | 3 | 1.20 |
| Oranges | 10 | 0.80 |

Right-aligning numeric columns keeps digits lined up and makes the table easier to scan.

GFM (GitHub Flavored Markdown) support

GitHub, GitLab, Zenn, Qiita, Notion, Obsidian, and most developer-facing platforms support GFM table syntax. Everything shown above works as-is on these platforms.

A few things worth remembering about GFM tables:

  • The header row is mandatory. You cannot create a headerless table in GFM
  • The separator row uses hyphens (---) — three per column by convention, though the spec allows fewer
  • Inline formatting (`code`, links, strikethrough) works inside cells
  • Some parsers require a blank line before and after the table to recognize it

Platform pipe-table support

The three table primitives — pipe | tables, colon alignment in the separator row (:---), and <br> for an in-cell line break — are supported unevenly across platforms. The table below summarizes each platform's behavior, with the per-platform notes underneath:

Platform Pipe tables Colon alignment (:---) In-cell <br>
GitHub Yes Yes Yes
GitLab Yes Yes Yes
Obsidian Yes Yes Yes
Notion Yes No No

Notes on the table:

  • GitHub follows the GitHub Flavored Markdown spec — Tables (extension), which defines pipe tables and colon alignment in the delimiter row. Cells are parsed as inline content, so inline raw HTML like <br> is allowed, and GitHub renders it as an in-cell line break.
  • GitLab Flavored Markdown documents the same pipe-table and alignment syntax, and its docs explicitly note that you can use a <br> tag to force multiple lines inside a cell.
  • Obsidian supports pipe tables and colon alignment in its documented table syntax, and in practice it renders a <br> tag as an in-cell line break.
  • Notion can import or paste pipe tables, but it converts them into its own table blocks rather than rendering GFM. Notion tables have no per-column alignment, so the alignment colons (:---) have no visible effect, and an in-cell <br> is not rendered as a line break.

The exact rules live in the GitHub Flavored Markdown spec — Tables (extension). Plain CommonMark does not define table syntax, so tables are technically a GFM extension. Renderers that follow strict CommonMark (with no extensions) will not render them as tables. For the full set of CommonMark vs GFM differences, see CommonMark vs GFM; for a quick reference of GFM table syntax — alignment, escaping, line breaks — see the GFM table cheatsheet.

Escaping pipes and special characters

A literal | inside a cell collides with the column separator and breaks the table. Two ways to write one safely:

| Command | Meaning |
| --- | --- |
| cmd1 \| cmd2 | backslash escape |
| cmd1 &#124; cmd2 | HTML entity |
  • \| (backslash escape) works on GitHub, GitLab, Notion, Obsidian, Zenn, Qiita, and most GFM renderers
  • &#124; (HTML numeric entity) is a reliable fallback when a renderer mishandles the backslash form, and it survives copy-paste between editors better than \|

To show a literal backslash in a cell, write \\. To insert a non-breaking space, use &nbsp;.

Common pitfalls

Newlines inside cells

The Markdown table spec does not support line breaks within a cell. If you need a visible break, write an HTML <br> tag directly, though not all platforms render it.

Empty cells

Leave a space (or nothing) between two pipes. A space is preferred for readability:

| A | B | C |
| --- | --- | --- |
| 1 | | 3 |

Mismatched column counts

If a data row has fewer columns than the header, most parsers pad with empty cells. If it has more, the extras are silently dropped. Keeping column counts consistent avoids surprises.

Large datasets — generate from CSV

Hand-writing a five-row table is fine. Past 20 rows, or with many columns, it becomes tedious and error-prone. Copy data from Excel or a spreadsheet as CSV, paste it into CSV to Markdown, and the tool handles pipe alignment and escaping for you.

For a step-by-step walkthrough, see How to Convert CSV to a Markdown Table. If you need to turn the resulting Markdown table into HTML, see Markdown to HTML conversion guide. To extract a Markdown table from existing HTML — a copied web page, a Notion export, or a CMS dump — see the HTML to Markdown guide.

Frequently asked questions

Can I create a Markdown table without a header?

Not in GFM. The header row and separator row are both required. If you do not need visible headers, you still have to include them — use placeholder text or empty header cells.

Yes. Inline Markdown like [text](url) and ![alt](image-url) works inside cells. Keep in mind that wide cells make the source hard to read, so links are usually the practical limit.

Can I control column widths?

Markdown has no column-width syntax. Renderers size columns based on content. For precise control, fall back to an HTML <table>.

Wrapping up

Markdown table syntax is straightforward: pipes for columns, hyphens for the separator, colons for alignment. Once you know these three pieces, you can build any table.

When the data gets large, skip the manual work. Paste CSV into CSV to Markdown and get a clean, correctly escaped table in seconds.