Skip to the tool
makeshortwork.com HTML Formatter

HTML Formatter & Minifier

Paste HTML, get it indented and readable — or minified back down. Whitespace-safe: what is inside pre, textarea, code and script is never touched. Nothing is uploaded.

 

The whitespace problem is the whole problem

Indenting a JSON file is boring. Indenting HTML is not, because HTML is the rare format where whitespace sometimes disappears and sometimes renders as a visible space — and the rule for which is which depends on the element, on its content model, and on CSS. A formatter that ignores this produces output that looks tidier and reads differently in the browser. The damage is subtle enough that it usually ships.

The clearest example takes two lines. Write <a>first</a><a>second</a> and the two links touch, with nothing between them. Put a newline between the tags to make it prettier and the browser collapses that newline into a single space, so the links now sit apart. Nothing in the markup warns you; the diff looks like formatting, the rendering changed. The same trap catches <strong>10</strong><span>%</span>, breadcrumb separators, icon-plus-label buttons and every price built from two inline spans.

So the rule this tool follows is narrow and mechanical: a line break may only replace whitespace that was already there, or sit at the edge of a block-level box, where the CSS line-box algorithm removes leading and trailing collapsible whitespace anyway. Where two inline items touch, they keep touching — even if that leaves a line far past your chosen width. A long line is a cosmetic problem. A moved space is a rendering bug.

One more detail that trips up regular-expression formatters: in JavaScript, \s matches U+00A0, the character &nbsp; produces. That character exists precisely because it does not collapse. Any formatter built on \s quietly eats the non-breaking spaces you fought to keep. This one treats only space, tab, newline, carriage return and form feed as collapsible.

The five elements that must never be re-indented

Inside <pre> and <textarea>, whitespace is content. Every space, every newline and every tab is rendered exactly as written, because those elements carry white-space: pre from the browser's own stylesheet. Add two spaces of indentation to the lines of a code block and you have edited the code sample on the page. Add a newline after <textarea> and you have changed the default value of a form field. This is the single most common bug in HTML beautifiers, and it is silent: the markup is still valid, the page still loads, only the content shifted.

<script> and <style> are a different kind of hazard. Their content is not HTML at all — it is raw text, and the parser is required to read it as text until the matching closing tag. That means if (a < b) inside a script is a comparison, not the start of a <b> element. Formatters that tokenize the whole file with one regular expression get this wrong and start "closing" tags that never opened, which corrupts everything after that point in the document.

Re-indenting script bodies is safe more often than not, so this tool does it — but only when the code contains no backtick. Inside a template literal, leading whitespace is part of the string, so shifting indentation changes what the script outputs. When a backtick shows up, the script body is emitted exactly as it came in. Preferring "unchanged and slightly ugly" over "pretty and possibly wrong" is the trade this whole tool is built on. CSS gets the same treatment; <code> is left byte-identical too, since it almost always lives inside a <pre> anyway.

Void tags, optional closing tags, and a tree that quietly drifts

Indentation depth comes from a stack, and the stack only works if the parser knows which tags actually open a level. Fourteen HTML elements are void: br, img, input, meta, link, hr, source and friends. They have no closing tag and no children. Push a <br> onto the stack and every line after it is indented one level too deep, forever, because the pop never comes. You can spot this failure instantly in bad formatters: the output staircases off to the right.

The mirror-image problem is optional closing tags. </li>, </p>, </td>, </tr>, </option> and several others may legally be omitted, and real templates omit them constantly. A parser that demands them will see <li>one<li>two</ul> as an unclosed list item and either bail out or nest the second item inside the first. This tool implements the implied-end-tag rules: a new <li> closes the open one, a <tr> closes the open cell, <tbody> closes <thead>, and a block-level start tag closes an open <p>. Tag names are also compared case-insensitively but printed with their original case, so SVG's <linearGradient> and viewBox survive — lowercasing those breaks the graphic.

When the structure genuinely cannot be resolved — a real unclosed <div>, a closing tag with no opening, an unterminated comment or quote — the tool stops and gives you your input back with the reason. That refusal is a feature. The alternative is a document that looks formatted and has silently lost a branch of its tree.

Formatted HTML and valid HTML are different things

People arrive at a formatter expecting it to fix their markup, and it will not, because the two jobs have almost nothing in common. Formatting is a whitespace operation: same tree in, same tree out, different line breaks. Validation asks whether your document obeys the specification — whether ids are unique, whether a <div> is allowed inside a <p> (it is not), whether <img> has alt, whether the attributes you used exist.

Beautifully indented HTML can fail validation on twenty counts, and gnarly minified HTML can pass cleanly. The one signal a formatter does give you is structural: if this tool refuses your file, something in the tag nesting is genuinely wrong and a validator will confirm it. For everything else, run the W3C Nu validator — it answers a question no formatter is qualified to answer.

When minifying pays, and when gzip already won

Minified HTML strips the whitespace between tags, collapses runs of spaces inside text to one, and optionally drops comments. The catch is that every one of those savings is exactly what a compression algorithm is best at. Repeated indentation is the most compressible byte pattern in existence, so gzip and Brotli have usually already removed it before it reaches the network.

Situation Does minifying help?
Static page served with gzip or Brotli Barely — typically a few percent on top of compression
HTML stored in a database column or JSON field Yes — no compression layer, and you pay per row
Email templates Yes — Gmail clips messages over roughly 102 kB
HTML embedded as a string inside JavaScript Yes — it lands in your JS bundle at full size
A page you still have to debug in production No — you are trading readability for bytes you already had

Comments are the interesting half of minification. Dropping them is usually free, with one exception this tool hard-codes: conditional comments (<!--[if lt IE 9]>) are logic, not annotation. They are kept even when comment removal is on, because deleting them changes behaviour in the one browser that reads them. Build-tool directives that live in comments deserve the same caution, which is why the checkbox exists.

Editor formatter or online formatter?

If you are working inside a project, your editor wins and it is not close. Prettier or the built-in formatter in VS Code, WebStorm or Zed runs on save, applies the same rules to every file, and can be enforced in CI so nobody's setup drifts. Formatting should be a property of the repository, not something a person remembers to do.

An online formatter earns its place in the situations where the editor is not involved: a chunk of HTML pasted out of a Slack thread, the response body from DevTools, a template pulled from a CMS field, a snippet from a colleague on a machine where you cannot install anything, or a quick check on a phone. It is also the fastest way to see the structure of markup you did not write — one paste, one click, and the nesting is legible. The moment that snippet becomes a file in a repository, hand it back to the editor.

What happens to your file

Nothing leaves the tab. The tool is a static page: the parser, the printer, the minifier and the syntax highlighter are JavaScript that downloads once and then runs locally. Choosing a file uses FileReader, which reads from your disk directly; there is no upload, no temporary storage and no request carrying your markup. Load the page, disconnect, and it still formats.

That matters more for HTML than people assume. Real markup carries session tokens in hidden inputs, API keys in inline scripts, customer names in email templates, internal hostnames in src attributes, and unreleased copy in comments. Pasting any of that into a formatter that round-trips through a server is a disclosure, however well-meaning the server. There is no size cap, no account and no rate limit here, because there is nothing on the other end to protect.

Frequently asked questions

Is my HTML uploaded anywhere?

No. The parser, the printer and the minifier are plain JavaScript that ships with the page and runs in your tab. Opening a file uses the browser's own FileReader, which reads from disk without a network request. You can put the page in airplane mode and it keeps working — that is the honest test, and most online formatters fail it because they POST your markup to a backend.

Will formatting change how my page renders?

That is the one thing it is built not to do. Content inside <pre>, <textarea>, <code>, <script> and <style> is copied byte for byte, and a line break is only ever inserted where whitespace already existed or at the edge of a block-level box, where browsers discard it. The single assumption that can bite you is CSS: if you set white-space: pre or display: inline on an element whose tag name says otherwise, no name-based formatter can know.

Why did it refuse to format my file and return it unchanged?

Because it hit something it could not read without guessing — an unclosed tag, a stray closing tag, a comment with no terminator, or a quote that never closes. Guessing is how formatters silently corrupt documents. The message names the tag it choked on; fix that one spot and the rest formats normally.

Does it fix invalid HTML?

No, and no formatter should. Formatting rearranges whitespace; validation is a separate judgement about whether your document obeys the spec. A file can be perfectly indented and still nest a <div> inside a <p>, duplicate an id, or leave an image without alt text. Run the W3C validator for that.

How much does minifying actually save?

On HTML alone, usually 10-25% of the raw bytes. Over the wire the number is far smaller, because gzip and Brotli already compress repeated whitespace to almost nothing — expect low single digits on top of compression. The real wins from minification are in email templates, inline HTML strings inside JavaScript, and anything stored in a database row where no compression layer exists.