Allin1Tool
Developer ToolsRuns in your browser

HTML Formatter

Reindent HTML from the browser's own parsed DOM, keeping pre, textarea, script and style contents byte for byte.

Share:

HTML Formatter workspace

The document is reindented from the tree the browser parses, so <pre>, <textarea>,<script> and <style> keep their contents byte for byte.

Source Editor

Input

Press Ctrl/Cmd + Enter to run.

Your draft is kept in this tab only (sessionStorage) and disappears when the tab closes. .

Result Console

Using HTML Formatter

  1. Paste your markup into the editor, or press Load example for a sample fragment.

  2. Choose an indent of 2 spaces, 4 spaces or Tab.

  3. Press Format HTML to reparse the document and print the tree back out.

  4. Compare the result with your source: any element that moved is a real nesting error.

The document is handed to DOMParser, the same parser the browser uses for a real page, and the output is generated by walking the resulting node tree. That is what lets it leave verbatim elements untouched, keep comments and attribute values intact, and handle angle brackets that appear inside scripts and attributes.

This page reindents markup. It does not validate it, minify it, or rewrite your tags — it takes the document, hands it to the browser, and prints the resulting tree back out with consistent indentation.

Why it parses instead of pattern-matching

The input goes through DOMParser, the same HTML parser the browser uses for a real page. The output is generated by walking the node tree it produces. That one decision is what makes the rest of this page's behaviour possible, because a parser knows the difference between a < that opens a tag and a < that is sitting inside a string, and a regular expression does not.

A regex-based formatter fails in three ways that are worth naming, because they are the same three every time:

  • <script>if (a < b && c > d)</script> was split at the comparison operators, which were read as tag boundaries. The script came out shredded.
  • Any attribute containing an angle bracket — <div data-tpl="<%= name %>"> or an inline SVG path with a > in its data — broke the element around it.
  • Whitespace inside <pre> was reindented, which changes what the browser renders. Preformatted text with the formatting removed is not preformatted text.

What is preserved byte for byte

The contents of <pre>, <textarea>, <script> and <style> are emitted exactly as they arrived. Not reindented, not trimmed, not touched. For the first two, whitespace is content and the page looks different if you change it. For the second two, the bytes are another language entirely and reindenting them is not this tool's job.

Comments are kept. Attribute values are re-serialised with their contents intact. Inline elements — <a>, <span>, <strong>, <code> and the rest of the list — stay on the line with the text around them, because breaking read the <a href="#">docs</a> first across three lines inserts whitespace that shows up in the rendered output as extra gaps.

Void elements are recognised, so <br>, <img>, <meta> and their siblings never get a spurious closing tag or an extra indent level.

The one setting

Indent is 2 spaces, 4 spaces or a tab. That is the whole configuration surface, and it is deliberate — a formatter with thirty options is a formatter whose output you cannot predict.

What it will not tell you

Because the browser's parser is forgiving by specification, it silently repairs a great deal. An unclosed <div> gets closed for you. A <p> inside a <p> gets split. A <td> outside a table gets relocated. The output is therefore a valid tree, but it may not be the tree you wrote, and the differences are the interesting part. If the result has moved elements around, you have found a real markup bug rather than a formatter bug — run the source through the W3C validator to see it named properly.

Nor does this page shrink anything. Formatting adds bytes on purpose. Minification for production belongs to a build step, and for the assets around the markup there is CSS Minifier and JS Minifier.

A note on very large documents

Parsing and reserialising a whole 2 MB page works, but the tree walk and the syntax-highlighted view are both linear in the size of the document and you will feel it. Formatting a component or a template fragment is what this is built for.

The markup you paste is parsed inside your own tab and never sent anywhere; the draft is kept in sessionStorage and disappears with the tab, or immediately if you use the "Clear it now" link.

Frequently asked

Does it fix broken markup?

Not on purpose. The browser's parser is forgiving by specification, so it closes an unclosed div, splits a paragraph nested inside a paragraph and relocates a stray table cell. The output is a valid tree, but if elements have moved you have found a genuine markup bug — the W3C validator will name it properly.

Will formatting change how my page renders?

It should not. Contents of pre and textarea are emitted unchanged because whitespace there is content, and inline elements such as anchors and spans stay on the line with the text around them so no extra gaps appear in the rendered output.

Does it reformat embedded CSS and JavaScript?

No. Script and style contents are copied out exactly as they arrived, because those are different languages and reindenting them is not this tool's job. Use the CSS and JavaScript tools for that work.

Why did the old regex-based version corrupt my code?

It could not tell an angle bracket in a tag from one inside a string. A comparison such as a < b inside a script was read as a tag boundary, an attribute containing a greater-than sign broke the element around it, and whitespace inside pre was reindented away.