HTML & CSS Beautifier That Keeps Template Tags

Paste HTML or CSS — it formats as you type. Auto-detects language, numbers lines, highlights syntax on input and output, flags unsupported syntax with the exact line, and supports Format, Lines, and Minify modes — with a before/after fidelity check to prove nothing was silently lost.

detected: {{effectiveMode.toUpperCase()}}

Input

{{ num }} ● Line {{ num }}: {{ errorMap[num].message }}
Waiting for input… ✓ Valid {{ effectiveMode.toUpperCase() }} ✕ {{ validationSummary }}
Output
Indent
{{human(origSize)}} → {{human(outSize)}} · {{deltaLabel}} · {{outLineCount}} lines · ✓ same content re-parsed from the output — nothing added or lost ⚠ content differs after re-parsing the output — see Before/after diff
{{ num }}

Re-parsing the output and minifying it produced different content than minifying the input directly — not just reformatted, something was actually added, dropped, or changed.

Re-parsing the output and minifying it produces exactly the same content as minifying the input directly — this diff below is whitespace/indentation only.

{{ row.kind === 'added' ? '+' : row.kind === 'removed' ? '−' : ' ' }} {{ row.text || ' ' }}

About this tool

Parses HTML or CSS into a lightweight tree with live syntax highlighting, gutter line numbering, and markup validation. Safely preserves dynamic template expressions (like Shopify/Liquid {{ ... }} and {% ... %}) and nested at-rules like @media, then re-renders according to your chosen action:

Content inside <pre>, <textarea>, <script>, <style> and <code> is preserved verbatim, and the syntax validator inspects for mismatched tags, unclosed braces/parentheses/quotes/comments and duplicate attributes — each finding points at the exact source line, shown as a dot in the gutter you can hover for the message.

Before/after diff re-parses the formatted output and minifies it, then compares that canonical form against minifying the input directly — proving the parser understood the same structure both times, not just that the renderer is consistent with itself. A whitespace-only text node between two inline elements (<b>A</b> <i>B</i>) is kept as a real space since dropping it would visibly run the words together; the same whitespace between two block-level elements is dropped, since that's what a browser does with it either way.

Parsing, validation and formatting happen entirely in your browser. Nothing you paste is uploaded.