HTML pretty print with a fixed, predictable style
This HTML pretty print tool runs Prettier's HTML formatter in the browser. Prettier parses the markup into a document tree and prints it again from scratch, so the result depends on the content, not on how the input happened to be indented. The same page always comes out the same way, and formatting that output a second time changes nothing. For a team, that means one agreed layout for templates and static pages, and diffs that show only real edits.
Want attribute-wrapping modes, a switch for indenting <head> and <body>, a Minify button, or output for markup that is too broken to parse? Use the HTML Formatter. It runs js-beautify, which re-indents whatever it receives and offers more layout switches but no enforced style.
One snippet through both engines
The input below has two unclosed <li> elements and an inline script:
<header class="site-header"><a href="#top" class="logo">Acme</a><nav><ul><li><a href="#features">Features</a><li><a href="#pricing" class="nav-link active" aria-current="page">Pricing</a></ul></nav></header><script>document.querySelector('.logo').onclick=function(){track('logo')}</script>
HTML Pretty Print (Prettier, 2 spaces, 80 columns):
<header class="site-header">
<a href="#top" class="logo">Acme</a>
<nav>
<ul>
<li><a href="#features">Features</a></li>
<li>
<a href="#pricing" class="nav-link active" aria-current="page"
>Pricing</a
>
</li>
</ul>
</nav>
</header>
<script>
document.querySelector(".logo").onclick = function () {
track("logo");
};
</script>
HTML Formatter (js-beautify, default settings):
<header class="site-header"><a href="#top" class="logo">Acme</a>
<nav>
<ul>
<li><a href="#features">Features</a>
<li><a href="#pricing" class="nav-link active" aria-current="page">Pricing</a>
</ul>
</nav>
</header>
<script>
document.querySelector('.logo').onclick = function() {
track('logo')
}
</script>
- Implied end tags are written out. Prettier adds the two
</li>tags the browser would infer; the beautifier leaves them open. - Every child of a block gets its own line. The logo link moves below
<header>instead of staying on the opening tag's line. - The line width is enforced. The Pricing link does not fit in 80 columns, so Prettier breaks it. It places the breaks inside the tags (
>Pricing</a) so that no whitespace is added around the link text and the page renders exactly as before. - Embedded JavaScript follows Prettier's JavaScript rules: double quotes, semicolons and a space in
function ().
On full documents there is one more visible difference: Prettier indents <head> and <body> inside <html>, while the main page leaves them at the same level unless you tick its option.
The two options and the settings behind them
Indent accepts 2, 3, 4 or 8 spaces or a tab, and applies to embedded CSS and JavaScript as well. Line width (20–320, default 80) is the column Prettier aims to stay within. The same button element fits on one line at a width of 120, but at 80 its text moves inside:
<button type="submit" class="btn btn-primary" data-track="signup" disabled>
Create account
</button>
All other settings are fixed at Prettier's defaults. Whitespace sensitivity follows each element's CSS display value, and when an opening tag is too long for the line, its attributes are placed one per line, with void elements such as <input> written as <input />. Scripts inside the page are always printed with double quotes and semicolons, because the quote and semicolon options are not exposed on this page.
Stricter than a beautifier
Because Prettier needs a valid tree, mis-nested markup stops it. Pasting <div><span>x</div></span> produces the error Unexpected closing tag "div", while the beautifier returns the snippet unchanged without comment. Treat the error as a hint to fix the source, or run the file through the HTML Validator for a fuller report. Optional end tags such as <li>, <p> and <td> are not errors; they are closed as shown above.
Getting the same result in your project
To apply this style across a repository, install Prettier as a pinned development dependency with npm install --save-dev --exact prettier and add a .prettierrc that mirrors the options you chose here:
{
"tabWidth": 2,
"printWidth": 80,
"htmlWhitespaceSensitivity": "css"
}
Run npx prettier "**/*.html" --write once, then npx prettier "**/*.html" --check in CI so unformatted files are caught before merge. Editors with Prettier support read the same configuration file, so formatting on save gives identical results. When a fragment must stay exactly as written, put <!-- prettier-ignore --> on the line above it. Real output from this tool:
<!-- prettier-ignore -->
<table><tr><td>1</td><td>2</td></tr></table>
<div><span>x</span></div>
The table is kept on one line as written, while the following <div> is formatted normally.
Templates and frameworks
This page uses Prettier's plain HTML parser. Vue single-file components and Angular templates have their own syntax for bindings and directives; use the Vue Formatter or the Angular Formatter for those, which run Prettier with the matching parser. Server-side template tags such as Blade or Jinja blocks are not part of HTML and may fail to parse; format the rendered output instead. Everything is processed locally in your browser and nothing is uploaded.