Upload or paste HTML and format it into clean, well-indented, easy-to-read markup you can copy or download in seconds.
.html file onto the editor. Works on snippets, full pages with embedded <style> / <script>, and email templates with deeply nested tables..html file. Everything runs in your browser — no upload, no sign-up.HTML formatting (also called beautifying or pretty-printing) adds structured whitespace and indentation so the document's hierarchy is visible at a glance. Browsers ignore most whitespace between tags, so reformatting is safe in almost all cases — it changes the source, not the render. A few situations make it genuinely useful:
<h2> -> <h4> jump than in a flat blob.<td> you need to edit.| Feature | XConvert HTML Formatter | Prettier (CLI/IDE) | js-beautify | Biome |
|---|---|---|---|---|
| Runs where | Browser (client-side) | Local Node | Local Node / browser | Local (Rust binary) |
| Default indent | 2 spaces | 2 spaces (tabWidth: 2) |
4 spaces | 2 spaces |
| Default quotes | Preserves source | Double (singleQuote: false) |
Preserves source | Double |
| Default print width | n/a (no wrap by default) | 80 chars (printWidth: 80) |
n/a | 80 chars |
| Opinionated | Light (indent + minify) | Yes — minimal config | No — highly configurable | Yes — ~97% Prettier-compatible |
| Formats embedded CSS/JS | Yes | Yes (embeddedLanguageFormatting: auto) |
Separate parsers | Yes |
| Install required | None | npm i -D prettier |
npm i -D js-beautify |
npm i -D --save-exact @biomejs/biome |
| Best for | Quick one-off cleanups, privacy-sensitive markup | Team consistency in repos | Fine-grained control | Performance-critical monorepos |
Note: Pretty Diff was archived in 2019 and its author moved to @prettydiff/prettydiff — for new work, pick one of the four above.
Formatters need to know which tags can hold children and which can't. The HTML5 spec defines exactly 14 void elements that take no closing tag and no content. Everything else is a container.
| Type | Examples | Closing tag? | Self-closing slash? |
|---|---|---|---|
| Void (HTML5 spec) | <area> <base> <br> <col> <embed> <hr> <img> <input> <link> <meta> <param> <source> <track> <wbr> |
No — and adding one is invalid | Optional. <br> and <br /> parse identically; the slash is ignored by HTML parsers |
| Container | <div> <span> <p> <section> <article> <a> <button> <table> <ul> |
Required: </div>, </span> ... |
n/a — <div /> is a parse error and treated as <div> |
| Raw-text | <script> <style> <textarea> <title> |
Required | Contents not parsed as HTML; preserved verbatim or formatted by language plugin |
| Preformatted | <pre> <code> (inside <pre>) |
Required | Whitespace inside is significant — the formatter must NOT reflow it |
XHTML and SVG do require the self-closing slash (<br />, <circle ... />). If you're authoring SVG-in-HTML, keep the slashes for portability.
Prettier ships with tabWidth: 2, useTabs: false, printWidth: 80, singleQuote: false (double quotes for attributes), htmlWhitespaceSensitivity: "css" (respect each tag's default display for whitespace decisions), bracketSameLine: false (the closing > of a multi-line element gets its own line), and embeddedLanguageFormatting: "auto" (format inline <style> / <script> contents). XConvert's defaults match — 2-space indent, no wrapping or quote rewriting unless you ask for it.
No. It only inserts, removes, or normalizes whitespace and indentation. It does not reorder attributes, change tag names, add or strip classes, decode entities, drop comments, or rewrite element nesting. A formatted document and its source produce identical DOM trees in the browser — the only render-level edge case is inline-element whitespace (gaps between adjacent <span> or <a> elements), which Prettier's htmlWhitespaceSensitivity: "css" is designed to preserve.
<br/> or <br>?In HTML5, both parse identically — the trailing slash on void elements is optional and ignored by parsers. The 14 HTML5 void elements (<area>, <base>, <br>, <col>, <embed>, <hr>, <img>, <input>, <link>, <meta>, <param>, <source>, <track>, <wbr>) never accept a closing tag either way. XHTML and inline SVG do require <br /> / <circle ... />, so if you're authoring SVG-in-HTML or shipping XHTML, keep the slashes. For plain HTML5, pick a convention and stay consistent — Prettier omits the slash unless bracketSelfClosing is set; js-beautify preserves whatever was in the source.
A formatter adds whitespace for human readability; a minifier removes it to cut bytes over the wire. They're complementary. Pretty-print during development and code review so structure is visible; minify during your build step so production HTML is smaller. XConvert's toolbar has both — toggle to Minify in the same tool, or jump to the HTML Minifier for the minify-first workflow.
<style> and <script> blocks too?Yes. The parser detects <style> and <script> blocks and runs their contents through CSS and JS formatting rules respectively — the same engines that power the CSS Formatter and JS Formatter. Prettier behaves the same way via embeddedLanguageFormatting: "auto". Inline style="..." attributes and inline onclick="..." handlers are left alone to avoid breaking expressions.
<pre> handled? Will it reflow my code blocks?No. <pre> and its descendants (including <code> nested inside <pre>) are preserved verbatim. The HTML spec treats whitespace inside <pre> as significant — line breaks and spacing are what make the rendered output look right. Every reasonable HTML formatter (Prettier, js-beautify, Biome, this one) special-cases <pre>, <textarea>, and <script> / <style> so their contents survive untouched.
No — formatters are dev-time tools. The whitespace they add costs bytes and slows page loads. Production builds should run a minifier (html-minifier-terser is the common Node choice). The typical pipeline: format on save in your editor, commit the pretty version, then minify during the build before deploying. Server-rendered frameworks (Next.js, SvelteKit, Rails view caching) already do this for you.
Not reliably. JSX uses className instead of class, allows {expression} interpolation, and embeds JS where HTML doesn't expect it; Vue templates have v-if, v-for, and :bind directives; Svelte adds {#if} / {:else} blocks. A generic HTML parser sees these as invalid attributes or text. For framework code, use Prettier with the matching plugin (prettier-plugin-svelte, the built-in Vue parser, or the JSX parser).
Performance is comfortable up to about 5 MB. The parser builds a DOM-like tree in memory, so very large server-rendered SPAs (10+ MB single-file dumps) may take several seconds and consume significant memory. For files that big, format individual components or partials rather than the whole document. Output stays entirely in your browser tab — nothing uploads.