Page & Bell

HTML Formatter / Beautifier

This formatter tokenizes HTML the way a parser does — tags, text nodes, comments, and raw-text blocks — then re-indents by real nesting depth instead of blindly splitting on angle brackets. That distinction matters: void elements like <br> and <img> never open phantom nesting levels, the contents of <script>, <style>, <pre>, and <textarea> pass through byte-for-byte, and malformed markup produces a warning list rather than a crash. Minify mode does the reverse: it strips comments and collapses inter-tag whitespace conservatively enough not to change what renders.

Paste HTML above — the formatted result appears here instantly.

How to use the html formatter / beautifier

  1. Paste HTML into the input (or click Load sample to see it work).
  2. Choose Beautify for readable, indented output or Minify for the smallest safe single-line version.
  3. Tune the indent (2 spaces, 4 spaces, or tabs), the attribute-wrap column, and whether inline elements stay on one line.
  4. Review any warnings — unclosed tags, stray closers — then copy the output.

What the beautifier actually does

The input is segmented into five token types: opening tags (scanned with quote-awareness so a > inside an attribute value never terminates the tag early), closing tags, comments, doctype/CDATA declarations, and text. Depth increases after a non-void opening tag and decreases at its closer. Text nodes have runs of whitespace collapsed to a single space — exactly what the browser does outside pre — and the “keep inline elements on one line” option joins a, span, b, em and friends with the surrounding text instead of exploding every word onto its own line. Opening tags longer than the wrap column with two or more attributes are broken one attribute per line, indented one extra level.

Minify mode, conservatively

Minification removes comments (preserving conditional <!--[if IE]> / <![endif]--> blocks, which old Outlook and IE actually parse), collapses whitespace runs inside tags but outside quoted attribute values, and reduces every text-node whitespace run to one space. A whitespace-only text node is dropped only when both neighbours are block-level — so <b>bold</b> <i>italic</i> keeps its word space, while the newline between </div> and <div> goes. Aggressive minifiers that strip all inter-tag whitespace shave a few more bytes and occasionally glue two words together on the rendered page; this one trades those bytes for safety.

Limits

Input is capped at 2 MB — beyond that a streaming build-time tool is the right instrument. The formatter does not validate against the HTML spec (use the W3C validator for conformance), does not reorder or deduplicate attributes, and does not touch SVG or MathML internals beyond generic tag rules. Everything runs in your browser; the document never leaves your machine, which also means it is safe for markup containing tokens, session IDs, or unreleased content.

Frequently asked questions

Why do void elements need special handling when indenting HTML?

Elements like br, img, input, meta, and hr never have closing tags, so a naive formatter that increments depth on every open tag drifts one level deeper after each one — ten <br> tags and your markup is indented forty spaces off. This tool keeps a void-element list (the 14 from the HTML spec) and never pushes them onto the nesting stack, so depth stays correct no matter how many appear.

Can minifying HTML actually change how a page renders?

Yes — whitespace between inline elements is significant. The classic case: inline-block siblings separated by a newline render with a roughly 4 px gap because the newline collapses to a space; remove it and the gap disappears, which can break deliberately spaced layouts. The same applies between <span> or <a> runs in text. That is why this minifier only drops whitespace-only text nodes when both neighbours are block-level tags, and trims text edges only against block boundaries.

What happens to my JavaScript and CSS inside the document?

Nothing. Content inside <script>, <style>, <pre>, and <textarea> is captured as a raw block during tokenization and emitted untouched in both modes — re-indenting a template literal or a regex containing </ would corrupt it, and <pre> exists precisely because its whitespace is meaningful. If you want the embedded code formatted too, run it through a dedicated JS or CSS formatter separately.

How are unclosed or mismatched tags handled?

Best-effort, never an error. <li>One<li>Two is legal HTML (the parser closes the first li implicitly), and this tool models the common implicit closers (li, p, td, th, tr, dd, dt, option). A closing tag with no matching opener is emitted where it stands with a line-numbered warning; tags still open at the end of input are listed too. The output is always produced — the warnings tell you what to fix.

When should I use an online formatter versus Prettier in my build?

Use the build tool for code you own: Prettier or dj-lint in a pre-commit hook formats consistently and forever. An online formatter wins for everything else — HTML scraped from a live page (View Source of a production site is usually minified), email templates exported from an ESP, CMS output you are debugging, or a snippet from a colleague. Formatting before reading a diff also turns a one-line minified blob into a reviewable change.

How much does minification actually save?

Typically 5–20% of raw size for hand-written HTML — indentation, comments, and blank lines. That is real but small next to gzip or brotli, which the server applies anyway and which compresses repetitive whitespace extremely well. Minify when you serve many small documents or count every byte (email, AMP); otherwise readable source plus brotli is usually the better trade.

Related tools