GFM pipe tables: alignment, separators, and sorting rows

Published: 2026-09-05

How GitHub-flavored Markdown pipe tables work—header and separator rows, left/center/right colon markers, column padding, and sorting body rows by column without uploading your draft.

GitHub Flavored Markdown (GFM) pipe tables are the tables you see in READMEs, pull requests, and many docs sites: rows of cells separated by |, plus a separator row of dashes that tells renderers “this is a table” and optionally how each column should align.

They are easy to write badly by hand. One short cell next to a long header makes pipes zigzag; a missing separator breaks rendering; sorting by score in a spreadsheet and pasting back often destroys alignment. A local formatter can pad columns and reorder body rows while keeping prose outside the table untouched.

LocalTools’ Markdown table formatter finds contiguous pipe-table blocks in your paste, aligns columns, preserves separator alignment markers, and can sort data rows by a chosen column—entirely in the browser.

Anatomy of a GFM pipe table

A minimal table needs at least two consecutive lines that contain |. The usual shape is:

  1. Header row — column titles.
  2. Separator row — only dashes (and optional : alignment markers) between pipes.
  3. Body rows — one or more data rows.
| Name | Score |
| --- | ---: |
| Ada | 95 |
| Bob | 8 |
Part Role
Header Labels for columns; usually not sorted away
Separator Required for GFM table recognition; encodes alignment
Body Data rows; safe to reorder when sorting

Leading and trailing pipes on each line are conventional (| a | b |) but some editors omit them. Formatters typically normalize to a consistent pipe style within a block.

Separator alignment markers

GFM uses colons on the separator cells to set column alignment in HTML output (text-align):

Separator cell Alignment
--- or :--- Left (default)
---: Right
:---: Center

Example:

| Left | Center | Right |
| :--- | :---: | ---: |
| a | b | c |

When you align or reformat, keep the colon pattern for each column. Changing :---: to --- silently left-aligns that column in GitHub’s renderer even if the cells still look centered in a monospace editor.

A formatter pads cell text with spaces so pipes line up in the source. Widths are based on visible character counts in the cells; wide emoji or combining marks can still look uneven in some fonts even when the source is padded correctly.

What counts as a table block

In mixed documents (a README with prose and several tables), contiguous lines that contain | form a block. Blank lines and non-pipe lines break the block. Formatting should:

  • Rewrite each block into aligned rows.
  • Leave surrounding Markdown (headings, lists, code fences) unchanged.
  • Preserve a trailing newline on the whole paste when one was present.

A single pipe-containing line is not enough—GFM needs the header/separator pattern (or at least two pipe rows for a naive aligner). If you paste a half-table, fix the structure first.

Sorting body rows (not the header)

Sorting a markdown table is almost always about data rows under the separator. The header and separator stay fixed; only body rows reorder.

Option Effect
No sort Align / pad only; row order unchanged
Sort by column Reorder body rows using that column’s cell text
Ascending / descending Direction of the comparison
Lexicographic vs numeric digits Lexicographic puts 10 before 2; numeric puts 2 before 10

Comparison is typically locale-aware and case-insensitive at the base letter level (Ada and ada group together). That matches how people expect name and label columns to sort—similar to sorting lines outside a table.

Tables without a separator row are awkward in strict GFM, but a practical tool may treat the first row as the header and everything after as body when you ask to sort. Prefer adding a real | --- | separator so GitHub and other renderers agree.

Practical workflow

  1. Paste a full table or a README fragment that includes one or more pipe tables.
  2. Confirm separator colons match the alignment you want (right-align numbers with ---:).
  3. Choose align only, or pick a sort column and direction (numeric digit order for scores, versions, and IDs).
  4. Copy the formatted output back into the file.
  5. If you reformatted both sides of a change, diff them so the review is about content, not pipe drift—see text diffs.

For HTML snippets elsewhere in the same doc, a separate HTML formatter is the right tool; pipe tables stay Markdown until a renderer turns them into <table>.

Common pitfalls

  • Missing separator — Many renderers show the pipes as ordinary paragraph text instead of a table.
  • Uneven column counts — A short row is often padded with empty cells; check that you did not drop a | mid-row.
  • Sorting the wrong column — Header labels stay put; verify you sorted by Score, not Name.
  • Lexicographic numbers — Without numeric ordering, 95 can sort “before” 8 incorrectly for humans.
  • Pipes inside cells — Literal | in cell text breaks naive splitting unless escaped or avoided; prefer rephrasing or HTML entities in edge cases.
  • Uploading drafts — README tables sometimes include internal codenames or metrics. Prefer a local-only pass.

Try it locally

Open the Markdown table formatter:

  1. Paste a GFM pipe table (or prose that embeds one).
  2. Leave sort off to align only, or choose a column, direction, and digit ordering.
  3. Copy the formatted output. Processing stays in your tab; nothing is uploaded.

Related reading

All learn articles