Markdown Table Generator, Explained

After reading this you will know how a Markdown table is built byte by byte, why alignment markers work the way they do, and how to paste spreadsheet data without breaking the output.

What a Markdown table actually is

A Markdown table is plain text. There is no hidden formatting, no binary structure, just pipe characters (|), hyphens (-), and colons (:) arranged into rows. A renderer like GitHub reads that text and draws a real HTML table from it.

Here is the smallest useful example. Three lines of text:

The output below is exactly what the tool produces. Copy it into any GitHub comment or README and it renders as a two-column table.

The raw text is:

| Name | Score |
| --- | --- |
| Ada | 95 |

Line 1 is the header. Line 2 is the delimiter row: it separates the header from the body and tells the renderer how many columns exist. Line 3 is data. Every row has the same number of pipes, and that is the whole contract.

The three parts of the syntax

Markdown tables have exactly three moving parts, and each one has a strict job.

Cell separator
The pipe | marks where one cell ends and the next begins. Leading and trailing pipes are optional in the spec, but the tool includes them because they make the columns line up in the raw text.
Delimiter row
The second line must contain one group of hyphens per column. A minimum of three hyphens (---) is conventional. Without this row, the block is not a table, it is just paragraphs with stray pipes.
Alignment colons
A colon on the delimiter row sets column alignment. :--- is left, ---: is right, :---: is centered, and plain --- leaves it to the renderer default (usually left).

That is the entire language. Everything else the tool does is cosmetic padding so the text is readable before it is rendered.

When to use it, and when not

Markdown tables are the right choice when the table is small and lives inside a text document: a README, a GitHub issue, a pull request description, or docs written in Markdown. They stay readable in a diff, and they need no external file.

They are the wrong choice past roughly 8 columns or 30 rows. The raw text stops fitting on screen, and editing a single cell means counting pipes across a very wide line. Markdown also has no support for merged cells, spanning headers, or per-cell formatting. If you need those, use real HTML or keep the data in a spreadsheet.

Markdown tables cannot contain a literal line break inside a cell. Every row is one physical line. If your source data has multi-line cells, they will collapse or break the table. Replace newlines with <br> or a space before you paste.

How alignment is decided

The tool offers per-column alignment, plus an Auto mode. Auto uses a simple rule: if every value in a column parses as a number, right-align it; otherwise left-align it.

Numbers read best right-aligned because the digits line up by place value. Compare these two columns of the same data:

Left-aligned versus right-aligned numbers
LeftRight
55
4242
10801080

In the right column the ones, tens, and hundreds sit in fixed positions, so 5, 42, and 1080 stack cleanly. That is why Auto exists: it applies the convention most documents want without you setting each column by hand.

The decision is per column, not per cell. A single non-numeric value flips the whole column to left. If a column of prices contains one entry like N/A, Auto treats the column as text and left-aligns it.

Escaping: the reason your table does not break

The pipe is the cell separator, so a pipe inside your data is a problem. If a cell contains the text a|b and you write it raw, the renderer sees two cells, and every row after it may shift.

The fix is escaping: write a backslash before the pipe, so a\|b. The renderer prints a literal pipe and does not split the cell. The tool does this for you on every cell, which is why pasted data with pipes, backslashes, or stray delimiter characters still produces a valid table.

\text{cells in row} = (\text{unescaped } | \text{ count}) - 1

Read this as a sanity check. If a data row has 4 unescaped pipes including the outer two, it defines 4 - 1 = 3 cells. When one row disagrees with the header count, an unescaped pipe is almost always the cause. The tool keeps every row at the same count by escaping, so this equation holds for all rows at once.

A worked example with the demo data

Turning three rows of CSV into an aligned table

Load the demo. It supplies a small table of people with a name, an age, and a city. The pasted source looks like this:

Name,Age,City
Ada Lovelace,36,London
Alan Turing,41,Manchester
Grace Hopper,85,New York

  1. The tool splits on commas into three columns: Name, Age, City.
  2. It scans each column for Auto alignment. Age holds only 36, 41, 85, so it is numeric and right-aligns. Name and City are text and left-align.
  3. It measures the widest value in each column to pad the raw text. Name needs 12 characters for Grace Hopper, City needs 10 for Manchester.
  4. It writes the header, then the delimiter row with a trailing colon on Age for right alignment, then the three data rows.

The result is:

| Name | Age | City |
| :----------- | --: | :--------- |
| Ada Lovelace | 36 | London |
| Alan Turing | 41 | Manchester |
| Grace Hopper | 85 | New York |

Notice the --: under Age: that is the right-align marker Auto chose. The padding spaces are ignored by the renderer, but they make the raw block readable in a plain editor.

See how alignment reshapes a column

The single idea worth playing with is how the alignment marker changes both the raw delimiter row and the rendered result. Move the control and watch the colons appear and shift.

Alignment changes only the delimiter row. Left is :---, center is :---:, right is ---:, and default is ---. The data cells stay the same text; only their position inside the rendered column moves.

Common mistakes

Most broken Markdown tables come from a short list of causes.

  • Missing delimiter row. Without the second line of hyphens the whole block renders as ordinary text. This is the most frequent error when tables are typed by hand.
  • Unescaped pipes. A raw | in a URL or a string splits the cell. The tool escapes these; hand-typed tables do not.
  • Ragged rows. If a data row has fewer cells than the header, renderers pad with blanks; if it has more, the extras are dropped or shift the table. Keep every row at the same cell count.
  • Tabs mistaken for columns. When you paste from a spreadsheet the separator is usually a tab, not a comma. Set the input format to match, or a single column will absorb the whole row.
  • Newlines inside cells. A cell that wraps to two lines in Excel becomes two rows or a broken table. Flatten it first.

Related tools

This generator is one step in a larger workflow. Depending on where your data starts and ends, these help before or after.

If your data is still in a spreadsheet file, run Excel → CSV Converter first to get clean rows. To inspect, sort, or trim columns before generating a table, use the CSV Viewer & Editor. When your source is JSON rather than CSV, convert it with the CSV ↔ JSON Converter or preview it in the JSON Table Viewer. For summarizing before you tabulate, the Pivot Table Maker groups and aggregates rows. If the data contains names or IDs you would rather not publish, mask them with the Data Anonymizer first. And to read columnar files, the Parquet & Feather Preview opens them without Python.

Frequently asked questions

Why does GitHub ignore my table?

Almost always a missing or malformed delimiter row. The line under the header must have one hyphen group per column, and there must be a blank line before the table starts. If either is off, GitHub treats the block as plain text.

How do I put a line break inside a cell?

Use the literal HTML tag <br> inside the cell. A real newline ends the row, so it cannot appear in the text. GitHub and most renderers honor <br> inside table cells.

Do the padding spaces matter?

No. Renderers strip leading and trailing spaces in each cell. The tool adds them only so the raw text lines up in a plain editor. You can delete every extra space and the rendered result is identical.

Does my data get uploaded anywhere?

No. The conversion runs entirely in your browser. Nothing you paste is sent to a server, so you can use it on private data offline.

What is the difference between center and default alignment?

Default (---) leaves alignment to the renderer, which usually means left. Center (:---:) explicitly places text in the middle of the column. If you want centered headers, you must set center; the default will not do it for you.