Developer FIELD NOTES · 4 MIN READ
Why Markdown Tables Drift Out of Alignment
Tables render fine while their source decays: padding, separator widths, alignment colons and ragged rows, and how a formatter repairs them all.
A markdown table can render perfectly while its source is a mess: pipes drift out of line, separator dashes keep whatever width they were born with, edited rows end up short a cell. Renderers forgive all of it. Humans and diffs do not. A formatter fixes the source — equal-width columns, normalized separators, rectangular rows — without changing what the table means.
What a formatter actually changes
Only whitespace and dashes. The formatter parses the table the way GitHub-flavored markdown does — a header row, a separator row of dashes, and data rows — then rebuilds it with every column padded to its widest cell. This misaligned input:
| Name | Role | Dept |
| --- | --- | --- |
| Ada | Enginee | Math |
| Grace | Admiral |
comes back as:
| Name | Role | Dept |
| ----- | ------- | ---- |
| Ada | Enginee | Math |
| Grace | Admiral | |
The short second row gained an empty cell (and a warning), every column is as wide as its widest entry, and the separator dashes now match the column widths — the same convention markdownlint and Prettier apply. In a rendered page the two versions are identical; in an editor, a diff, or a code review, only the second one is readable.
Alignment markers: keep, force, or strip
The colons in a separator row control column alignment when the table renders: :--- left, :---: center, ---: right. In the default keep mode the formatter preserves your markers exactly and only normalizes the dash count. This mixed-alignment table:
| ID | Amount | Note |
| :- | ---: | :-: |
| 1 | 1200 | rent |
| 22 | 5 | tip |
comes back with the numbers right-aligned in the source, matching how they will render:
| ID | Amount | Note |
| :-- | -----: | :---: |
| 1 | 1200 | rent |
| 22 | 5 | tip |
Force modes (left, center, right) override every column; none strips the markers entirely. Because padding respects each column's alignment, the source can mirror the rendered layout — numbers flush right, text flush left.
Ragged rows and quiet repairs
Real tables are ragged. Rows with too few cells are padded with empty cells so the table stays rectangular; rows with more cells than the header keep their extras rather than silently dropping data. Both cases are reported in a warnings list — row 2 had 2 cells — padded to 3 — so nothing is "fixed" invisibly. And a table whose separator row is missing altogether does not have to be a dead end: an option adds one below the header with left alignment, turning a loose list of pipe-delimited rows into a proper table.
Escaped pipes and other mess
A literal pipe inside a cell would end the cell, so markdown escapes it as \|. The formatter splits rows on unescaped pipes only, keeps the escapes intact in the output, and handles the usual file disorder silently: CRLF line endings from Windows editors, trailing blank lines, rows with or without enclosing pipes. The goal is that whatever a real-world table looks like on the way in, it comes out canonical.
Formatter versus generator
The two table tools face opposite directions. The generator builds a markdown table from raw delimited data — CSV, TSV, semicolon lists — when the table does not exist yet. The formatter takes a table that already exists and cleans it up without touching cell contents. In practice they chain: generate a table from a CSV export, then format it to align the columns for the README. (How the table syntax itself works is covered in markdown explained, and delimited data in how CSV files work.)
Try it yourself
Paste the ragged Name/Role/Dept table above into the Markdown Table Formatter and compare the aligned output, warnings included, with the original. Then build a fresh table from CSV data in the Markdown Table Generator, and render both with the Markdown to HTML Converter to confirm that tidier source produces identical HTML.