Stop hand-aligning markdown tables in 2026
Use a visual, spreadsheet-style editor that exports GitHub-Flavored Markdown so you stop counting spaces by hand. You paste a CSV export, tweak the alignment per column, and the markdown updates as you type. The editor I cover here runs in your browser and never uploads your data. It cut a 47-minute chore down to about two minutes for me.
Quick disclosure: the Markdown Table Generator I link to below is one I built. I'd tried five other generators. Every one either logged my table data to a server or buried the alignment controls behind a paywall, and a couple choked on cells that contained a pipe character. So I wrote my own. It's free and runs entirely client-side. There's no signup, and nothing gets uploaded. If you know a better one, tell me.
The 47 minutes I'll never get back
Three weeks ago I sat down to update the README for an internal CLI tool. It had grown to fourteen flags, and a teammate asked for a table documenting each one. I typed it by hand the way I always had, lining up the pipes with spaces so the raw file looked tidy in my editor.
Then I added one more flag. Every column shifted. I spent the next stretch nudging spaces around like it was 2011, and when I finally pushed, the diff came back as a wall of red and green because the renderer had touched every line in the block. The actual change was a single row.
I checked the clock afterward. 47 minutes on one table. Not the docs, not the code. The table itself.
Here's the thing that really gets me about those diffs. When you re-pad a whole table to fit one new row, every line registers as changed, so a reviewer can't see what you actually edited. They either skip the table review entirely or waste time eyeballing forty lines to find your one real change. Both outcomes are bad, and both come from a formatting quirk rather than anything meaningful.
Markdown tables look simple, and for a 2x2 they are. The trouble starts once a table grows past a handful of rows: manual alignment stops paying for itself, and any single edit reshuffles the whole block. The alignment markers don't help my memory either. Left is :---, right is ---:, center is :---:, and I still open the docs every time to remember which side the colon goes on.
This is a tiny problem, which is exactly why it irritates me so much. Nobody plans for it. You don't budget time to reformat a table the way you'd budget for a refactor, so it sneaks up during work you thought was basically finished and quietly eats real minutes. Multiply that across every doc and changelog you touch in a year, and the total stops being small.
What the generator actually does
There's no magic under the hood. A table generator holds your data as a 2D array and re-renders the text output on every keystroke. The fiddly part is the padding. Each column's width equals the length of its longest cell. Every other cell in that column gets padded to match, and the separator row carries the alignment colons.
Here's the core of that logic in plain JavaScript. Save it as table.js and run it with Node:
function toMarkdownTable(rows, aligns) {
const widths = rows[0].map((_, c) =>
Math.max(...rows.map(r => String(r[c]).length))
);
const pad = (text, width, align) => {
const s = String(text);
const gap = width - s.length;
if (align === "right") return " ".repeat(gap) + s;
if (align === "center") {
const left = Math.floor(gap / 2);
return " ".repeat(left) + s + " ".repeat(gap - left);
}
return s + " ".repeat(gap);
};
const row = cells =>
"| " + cells.map((c, i) => pad(c, widths[i], aligns[i])).join(" | ") + " |";
const sep = widths.map((w, i) => {
const dash = "-".repeat(Math.max(3, w));
if (aligns[i] === "right") return dash.slice(0, -1) + ":";
if (aligns[i] === "center") return ":" + dash.slice(1, -1) + ":";
return dash;
});
const [header, ...body] = rows;
return [
row(header),
"| " + sep.join(" | ") + " |",
...body.map(row),
].join("\n");
}
const data = [
["flag", "type", "default"],
["--verbose", "bool", "false"],
["--retries", "int", "3"],
];
console.log(toMarkdownTable(data, ["left", "left", "right"]));
Run node table.js and you get a clean, aligned table out the other side. A visual editor wraps this same logic in a spreadsheet grid, so you can tab between cells and paste a block of CSV while the markdown updates live in a pane beside the data. You can try the editor here and drop in a CSV export straight from a spreadsheet app; it parses the rows in the browser and keeps the data on your machine.
The part I care about most is that CSV import. Most of my tables already exist somewhere, usually as a spreadsheet export or a query result. Retyping them by hand is the step that actually wastes my afternoon, so being able to paste raw CSV and get GFM back is the whole point for me.
One detail that took me longer than I'd like to admit: cells that contain a pipe character. In GFM a raw | inside a cell breaks the table unless you escape it as \|. The generator does that escaping for you on the way out, which is the single bug that pushed me off two of the hosted tools I'd been using. I don't know why so many of them skip it, but they do.
How it stacks up against the alternatives
I didn't build this in a vacuum. There are several common ways to make a markdown table, and each comes with a tradeoff. Here's how I'd line up the ones I actually reached for before I gave up and wrote my own:
| Approach | CSV import | Alignment controls | Works offline | Keeps data local |
|---|---|---|---|---|
| This generator | Yes | Per-column buttons | Yes | Yes |
| tablesgenerator.com | Partial | Yes | No | Sends to a server |
| VS Code table extension | No | Auto-format only | Yes | Yes |
| Typing it by hand | No | Manual colons | Yes | Yes |
The VS Code formatter is genuinely good if you already have the rows typed out. It'll re-align an existing table for you on save, which covers the "I added a row and everything shifted" pain nicely. What it won't do is take a CSV dump and build the table from scratch, and that build step is exactly where my time goes. The hosted generators do handle CSV, but the ones I tried either round-tripped my data through their backend or put alignment behind an account wall. For a thirty-second job, that's too much friction and too much trust to ask.
None of these are bad tools, to be clear. The hand-typed table is fine until it grows. The VS Code extension is the right answer if your rows are already in the file. My complaint is narrow: I wanted one workflow that started from a CSV and ended at GFM I could trust, without an account in the middle.
So the gap I kept hitting was a tool that could import CSV and give me real alignment controls without shipping my data off my laptop. That combination is what I ended up building.
When I don't reach for it
A generator isn't always the right call, and pretending it is would be dishonest.
If the table is tiny, say two columns and two rows, just type it. Opening any tool is slower than the keystrokes, and you won't fight alignment at that size anyway.
If the table is produced from data inside a script or a CI job, generate the markdown in code instead. The function above is a fine starting point, and a GUI parked in the middle of an automated pipeline defeats the purpose.
If you need merged cells or row spans, plain markdown can't express either of those. You'll have to drop down to raw HTML inside your markdown, or pick a different format. No generator can paper over a limitation that lives in the spec itself.
And honestly, I still hand-write a quick table now and then when I'm offline and can't be bothered to open a browser tab. Old habits stick around.
FAQ
Q: Does it output GitHub-Flavored Markdown specifically?
A: Yes. The separator row uses the colon syntax GitHub renders, so whatever alignment you set shows up correctly once the table lands in a repo or an issue.
Q: Can I paste data from Excel or Google Sheets?
A: Yes. Copy a range and paste it straight in. Spreadsheet copy usually arrives as tab-separated text, and the editor reads that the same way it reads CSV, so you don't need to export a file first.
Q: Is any of my table data sent anywhere?
A: No. Parsing and rendering both happen in your browser, and nothing about the table leaves your machine. That was the main reason I stopped using the hosted options I'd been relying on.
Q: What about very wide tables?
A: They work, but think about whoever reads the result. A table with twelve columns is painful in a rendered doc and it'll scroll sideways on a phone. I try to keep mine under six columns when the data lets me.
Q: Does it handle alignment per column or all at once?
A: Per column. Each column gets its own alignment toggle, so a numbers column can sit right-aligned while the text label beside it stays left. That mixed alignment is the part raw typing makes genuinely tedious, since every change recomputes the padding by hand.
Written with AI assistance and human review. Try the tool at aidevhub.io/markdown-table-generator.
Top comments (0)