X Xerobit

Markdown Tables — How to Create and Format Tables in Markdown

Markdown tables use | and - to define columns and rows. Here's the full syntax for creating tables, aligning columns, handling special characters, and working with tables in...

Mian Ali Khalid · · 4 min read
Use the tool
Markdown Preview
Live Markdown preview with GitHub-flavored syntax. Tables, task lists, code blocks, strikethrough. Side-by-side editor and rendered output.
Open Markdown Preview →

Markdown tables use pipe characters (|) to separate columns and dashes (-) to define the header row separator. They’re part of GitHub Flavored Markdown (GFM) and supported in most Markdown renderers.

Use the Markdown Preview to preview tables as you write them.

Basic table syntax

| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Row 1A   | Row 1B   | Row 1C   |
| Row 2A   | Row 2B   | Row 2C   |

Renders as:

Column 1Column 2Column 3
Row 1ARow 1BRow 1C
Row 2ARow 2BRow 2C

Rules:

  • Header row separated from body by a row of dashes
  • At least 3 dashes per column in the separator row
  • Leading and trailing | are optional but recommended for readability

Column alignment

Add : to the separator row to control alignment:

| Left     | Center   | Right    |
| :------- | :------: | -------: |
| Left 1   | Center 1 | Right 1  |
| Left 2   | Center 2 | Right 2  |
LeftCenterRight
Left 1Center 1Right 1
Left 2Center 2Right 2
  • :--- — left-align (default)
  • :---: — center-align
  • ---: — right-align

Minimal table syntax

You don’t need to align the pipes:

| A | B | C |
|---|---|---|
| 1 | 2 | 3 |
| 4 | 5 | 6 |

The separator just needs at least one dash per column.

Tables with formatting inside cells

Markdown formatting works inside table cells:

| Feature     | Supported | Notes                         |
| :---------- | :-------: | :---------------------------- |
| **Bold**    | ✅        | Use `**text**`                |
| *Italic*    | ✅        | Use `*text*`                  |
| `Code`      | ✅        | Use backticks                 |
| Links       | ✅        | `[text](url)` works           |
| Images      | ✅        | `![alt](url)` works           |
| Line breaks | ❌        | Not supported in GFM tables   |
| Lists       | ❌        | Can't nest lists in cells     |

Escaping pipe characters

Use \| to include a literal pipe inside a cell:

| Operator | Meaning       |
| -------- | ------------- |
| `\|`     | Logical OR    |
| `&&`     | Logical AND   |
| `\|\|`   | Double pipe   |

Or use HTML entity | for a pipe: |

Practical table examples

Comparison table

| Feature         | Free Plan | Pro Plan | Enterprise |
| :-------------- | :-------: | :------: | :--------: |
| API calls/month | 1,000     | 50,000   | Unlimited  |
| Storage         | 1 GB      | 50 GB    | Custom     |
| Support         | Community | Email    | Dedicated  |
| Price           | $0        | $29/mo   | Contact    |

Method reference table

| Method              | Returns   | Description                    |
| :------------------ | :-------- | :----------------------------- |
| `arr.push(item)`    | `number`  | Appends item, returns length   |
| `arr.pop()`         | `T`       | Removes and returns last item  |
| `arr.shift()`       | `T`       | Removes and returns first item |
| `arr.unshift(item)` | `number`  | Prepends item, returns length  |
| `arr.slice(s, e)`   | `T[]`     | Returns subarray (non-mutating)|

Keyboard shortcuts

| Action           | Mac           | Windows/Linux   |
| :--------------- | :------------ | :-------------- |
| Copy             | `⌘ C`         | `Ctrl + C`      |
| Paste            | `⌘ V`         | `Ctrl + V`      |
| Find             | `⌘ F`         | `Ctrl + F`      |
| Save             | `⌘ S`         | `Ctrl + S`      |
| Undo             | `⌘ Z`         | `Ctrl + Z`      |

Generating tables from data

For large tables, generate them programmatically:

JavaScript

function markdownTable(headers, rows) {
  const colWidths = headers.map((h, i) =>
    Math.max(h.length, ...rows.map(r => String(r[i] || '').length))
  );
  
  const pad = (str, len) => str.padEnd(len);
  
  const header = '| ' + headers.map((h, i) => pad(h, colWidths[i])).join(' | ') + ' |';
  const sep = '| ' + colWidths.map(w => '-'.repeat(w)).join(' | ') + ' |';
  const body = rows.map(row =>
    '| ' + row.map((cell, i) => pad(String(cell || ''), colWidths[i])).join(' | ') + ' |'
  );
  
  return [header, sep, ...body].join('\n');
}

const headers = ['Name', 'Age', 'City'];
const rows = [['Alice', 30, 'London'], ['Bob', 25, 'Paris']];

console.log(markdownTable(headers, rows));
// | Name  | Age | City   |
// | ----- | --- | ------ |
// | Alice | 30  | London |
// | Bob   | 25  | Paris  |

Tables in different Markdown flavors

FlavorTables
CommonMarkNot supported (extension)
GitHub Flavored Markdown (GFM)Yes
PandocYes
MultiMarkdownYes
R MarkdownYes
VS Code previewYes
Most static site generatorsYes

Standard CommonMark doesn’t include tables — they’re an extension. If your renderer doesn’t support them, you’ll need HTML <table> tags instead.

HTML table as fallback

When Markdown tables aren’t supported:

<table>
  <thead>
    <tr><th>Name</th><th>Value</th></tr>
  </thead>
  <tbody>
    <tr><td>Alpha</td><td>1</td></tr>
    <tr><td>Beta</td><td>2</td></tr>
  </tbody>
</table>

Related posts

Related tool

Markdown Preview

Live Markdown preview with GitHub-flavored syntax. Tables, task lists, code blocks, strikethrough. Side-by-side editor and rendered output.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.