What the minifier changes
HTML minification is mostly about whitespace and the small things around it. This page runs html-minifier-terser with a deliberately conservative set of transforms:
- Whitespace collapsing. Every run of spaces, tabs and line breaks between tags or inside text becomes a single space. It is not removed completely: with conservative collapsing, a place that had whitespace keeps one space. That matters because
Hi <strong>Aisha</strong>,renders differently fromHi<strong>Aisha</strong>,, and inline elements, buttons andinline-blocklayouts depend on those gaps. - Comments are removed. A comment at the very start of the input leaves one leading space behind, which is harmless.
- Boolean attributes are shortened:
checked="checked",disabled="disabled"andautofocus=""all become the bare attribute name. - Inline CSS in
<style>blocks andstyleattributes is compressed:margin: 0pxbecomesmargin:0,#333333becomes#333. - Inline JavaScript in
<script>elements and event-handler attributes such asonclickis minified with Terser, which can inline constants as well as strip spaces.
On a full page with indentation, the saving is usually 10 to 25 percent; the order confirmation example drops from 645 to 533 bytes. Pages heavy with inline scripts and styles gain more.
What stays exactly as written
Several things are left alone on purpose. Content inside <pre> and <textarea> keeps every space and line break, because there whitespace is visible. Character references are not decoded, so &, and $ stay as typed and cannot turn into markup or invisible characters by accident. Attribute values keep their quotes, optional closing tags such as </li> and </p> are not removed, and self-closing slashes like <br/> are kept, so the output still works for XHTML consumers and email clients that are picky about markup. Doctype, <head> and <body> stay in place. Attributes are not sorted and class names are not reordered, so selectors and scripts that look for an exact class value keep matching.
Skipping the riskier transforms costs a few bytes compared with aggressive settings, but it means the minified page needs no visual check: if it rendered before, it renders the same after.
Validation and workflow
The input is parsed by Prettier’s HTML parser before the minifier sees it, so an unclosed opening tag or a closing tag with no matching opener is reported with its line and column instead of producing quietly damaged output. Note that HTML’s own error recovery is generous: an unclosed <li> or <p> is valid because those end tags are optional.
Paste the HTML or open a file; the page starts in minify mode. Use Ctrl/Cmd+Shift+M to see the same input beautified, and Ctrl/Cmd+Shift+C to copy the compact version. The Preview tab renders your input in a sandbox, which helps when minifying an email template you cannot easily test elsewhere. The formatting options (Whitespace sensitivity, One attribute per line, Keep > on the last attribute line) only affect the beautified view. Templates containing customer data stay in your browser while you work.
Examples
Order confirmation page
The style block and script are compressed and the comment removed, while the <pre> table and the $ and & references are untouched.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Order confirmed</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0px; }
.total { font-weight: bold; }
</style>
</head>
<body>
<!-- order summary -->
<h1>Thanks, Aisha!</h1>
<p>Your order <strong>ord_8f2k1</strong> ships tomorrow.</p>
<p class="total">Total: S$129.90 & free delivery</p>
<input type="checkbox" checked="checked" disabled="disabled"> Email me updates
<pre>
KB-104 x1
MS-220 x2
</pre>
<script>
const orderId = "ord_8f2k1";
console.log("Loaded order", orderId);
</script>
</body>
</html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Order confirmed</title> <style>body{font-family:system-ui,sans-serif;margin:0}.total{font-weight:700}</style> </head> <body> <h1>Thanks, Aisha!</h1> <p>Your order <strong>ord_8f2k1</strong> ships tomorrow.</p> <p class="total">Total: S$129.90 & free delivery</p> <input type="checkbox" checked disabled> Email me updates <pre>
KB-104 x1
MS-220 x2
</pre> <script>const orderId="ord_8f2k1";console.log("Loaded order",orderId)</script> </body> </html> Email table cell with an inline style
The style attribute is minified and the comment dropped, but a single space remains around each inline element so the sentence reads correctly.
<table role="presentation" width="100%">
<tr>
<td style="padding: 16px 24px; font-family: Arial, sans-serif; color: #333333;">
<!-- greeting -->
Hi <strong>Aisha</strong>,
your refund of <b>S$39.50</b> is on its way.
</td>
</tr>
</table>
<table role="presentation" width="100%"> <tr> <td style="padding:16px 24px;font-family:Arial,sans-serif;color:#333"> Hi <strong>Aisha</strong>, your refund of <b>S$39.50</b> is on its way. </td> </tr> </table> Signup form with boolean attributes
required, autofocus and selected are reduced to bare attributes, and the onclick handler is minified like any other script.
<form action="/subscribe" method="post">
<label for="email">Email</label>
<input id="email" type="email" required="required" autofocus="">
<select name="plan">
<option value="monthly" selected="selected">Monthly</option>
<option value="yearly">Yearly</option>
</select>
<button type="submit" onclick=" track( 'subscribe' ); ">Subscribe</button>
</form>
<form action="/subscribe" method="post"> <label for="email">Email</label> <input id="email" type="email" required autofocus> <select name="plan"> <option value="monthly" selected>Monthly</option> <option value="yearly">Yearly</option> </select> <button type="submit" onclick='track("subscribe")'>Subscribe</button> </form> Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Unexpected closing tag "span". It may happen when the tag has already been closed by another tag.Explained | A closing tag does not match any open element, often a typo or a leftover from deleting markup. | Remove the stray closing tag or rename it to match the element it should close. |
Opening tag "div" not terminated. | An opening tag is missing its >, so the parser runs into the next tag while still reading attributes. | Add the > at the end of the tag; check for an unclosed attribute quote as well. |
Unexpected closing tag "p". It may happen when the tag has already been closed by another tag. | A block element such as <div> or <ul> inside a <p> closes the paragraph implicitly, so the later </p> has nothing to close. | Do not nest block elements inside <p>; use a <div> as the container instead. |
Frequently asked questions
Will minifying HTML break my layout?
Not with these settings. Whitespace is collapsed to one space rather than removed, so inline elements keep their gaps, and <pre> and <textarea> content is preserved.
Does it minify the CSS and JavaScript inside the page?
Yes. <style> blocks and style attributes are compressed as CSS, and <script> blocks and inline event handlers are minified with Terser.
Why does the output still have spaces between tags?
Conservative collapsing keeps one space wherever the source had whitespace, because removing it can change how inline content renders. It costs a few bytes and avoids layout surprises.
Are HTML comments removed?
Yes, all of them. If a comment must survive, such as a marker a server-side include looks for, add it back after minifying.