HTML / CSS / JS Beautifier & Minifier
Beautify or minify HTML, CSS, and JavaScript source
How to HTML / CSS / JS Beautifier & Minifier Online
Beautify or minify HTML, CSS, and JavaScript source code.
- Pick the language (JavaScript, HTML, or CSS) from the dropdown. Switching language loads an example unless you have already typed something.
- Set indent width for the beautify direction (2 is standard).
- Paste your source into the input box.
- Click Beautify to pretty-print the source with consistent indentation. Click Minify to strip whitespace and (for JavaScript) compress identifiers.
- JavaScript minification lazy-loads `terser` (~200 KB) on first use. Subsequent runs are instant.
- The output panel shows the result plus a byte count and percentage relative to the input — handy for measuring minify ratios.
- Click Copy to put the result on your clipboard.
About HTML / CSS / JS Beautifier & Minifier
The beautify-and-minify cycle is one of the oldest and most-used roundtrips in front-end work. You inherit minified production code and need to read it (beautify). You have hand-written source you want to ship at minimum size (minify). You scraped a JavaScript snippet and want to understand what it does (beautify). You need to inline a small CSS payload and every byte matters (minify). The tool here handles all three languages — HTML, CSS, JavaScript — in both directions with a single interface.
The **beautify** path uses **`js-beautify`** — the same library that powers VS Code's built-in formatter (for older builds), Atom, Brackets, and many in-browser editors. The output is opinionated but matches what most teams converge on: 2-space indents by default, opening braces on the same line as the function/conditional, blank lines preserved where they exist in source, and HTML `<script>` and `<style>` blocks reindented as their respective languages. The result is what `Format Document` in your IDE would produce, give or take editor-specific overrides.
The **minify** path is more interesting because the right algorithm depends on the language.
**JavaScript** minification needs a real AST transformer. `terser` (the maintained successor to UglifyJS) is the standard — it parses your code, applies dozens of transformations (variable renaming, constant folding, dead-code elimination, expression inlining, boolean compression), and re-emits a compressed form. It is also large (~200 KB compressed) which is why the tool lazy-loads it only when you click Minify on JavaScript. The cost is one chunk download on first use; the benefit is keeping the rest of the site fast for everyone else. Typical compression ratio is 30–60% on application code, higher on libraries with lots of comments.
**CSS** minification is a much simpler problem: strip comments, collapse runs of whitespace, drop spaces around punctuation that does not need them (`{`, `}`, `:`, `;`, `,`, `>`, `+`, `~`), and remove the optional trailing `;` before `}`. There is no equivalent of variable renaming because CSS selectors, properties, and values are all referenced externally. The tool implements this as a small inline function (under 1 KB) — there is no need to pull in a full library. Typical compression ratio is 20–30%.
**HTML** minification is the trickiest of the three because HTML's whitespace rules depend on context. Whitespace inside a `<pre>` block is significant. Whitespace inside a `<script>` or `<style>` block is JavaScript or CSS source. Whitespace between block-level elements is usually safe to strip; whitespace between inline elements sometimes affects rendering. The tool takes a conservative approach: strip HTML comments (preserving Internet Explorer conditional comments), collapse multiple spaces to one, and remove whitespace between tags — but preserve every `<pre>`, `<textarea>`, `<script>`, and `<style>` block byte-for-byte. More aggressive HTML minifiers (`html-minifier-terser`) can drop optional closing tags and inline-minify embedded scripts, but they occasionally break real pages, so we stop short of that.
A few subtleties worth knowing. **Minification is not transpilation.** If your JavaScript uses optional chaining or top-level await, the minified output uses the same modern syntax — `terser` does not downgrade. For older-browser support, transpile first with Babel or esbuild, then minify. **Mangling preserves globals.** Top-level function declarations, named exports, and properties on the global object keep their names so external code can still reference them. Only local variables get renamed. **Source maps are not produced** by this tool — the byte savings are visible in the output, but if you need to debug minified code in production, run the same minifier as part of your build pipeline so source maps emit alongside.
Everything runs in your browser. `js-beautify` (~50 KB compressed) is bundled with the tool's page chunk. `terser` (~200 KB compressed) is lazy-loaded from your own origin on first JavaScript-minify click and cached for the rest of the session. The CSS and HTML minifiers are inline. Nothing about your source is transmitted to any server — confirmed by the absence of network requests during beautify and minify operations.
Related Tools
Frequently Asked Questions
What library handles the beautify step?
`js-beautify` — the de facto standard JavaScript beautifier, used by Atom, Brackets, and dozens of other editors. It handles JavaScript (including TypeScript, JSX, modern syntax), HTML (with embedded `<style>` and `<script>` blocks reindented appropriately), and CSS. The output matches what running 'Format Document' in VS Code with the same indent setting would produce.
Why does minifying JavaScript load a ~200 KB chunk?
Because JavaScript minification is genuinely hard — it requires a real AST-level transformer that can rename variables safely, strip dead code, and inline expressions without changing semantics. `terser` (the maintained successor to UglifyJS) is the standard, and it weighs about 200 KB compressed. The tool lazy-loads it only when you click Minify on JavaScript, so the rest of the site is not penalized. Loading happens once per page visit — subsequent minify runs are instant.
What does the JavaScript minifier actually do?
Several optimizations in sequence: rename local variables to single letters (`mangle`), remove all comments and whitespace, fold constant expressions (`1 + 1` → `2`), drop unreachable code, inline single-use variables, and replace boolean literals (`true` → `!0`). The output is semantically identical to the input but typically 30–60% smaller. Global names and named exports are preserved so the minified code can still be referenced from outside.
Why is the HTML minifier conservative?
Because aggressive HTML minification breaks too often. The minifier here strips comments and collapses whitespace between tags (the only safe transformations) while preserving the content inside `<pre>`, `<textarea>`, `<script>`, and `<style>` blocks — places where whitespace is semantically meaningful. More aggressive HTML minifiers (`html-minifier-terser`) can drop optional closing tags, remove quotes from attributes, and inline minify embedded scripts/CSS, but each of those steps occasionally breaks real pages. If you need that, run html-minifier-terser as a build step.
Does CSS minification change my selectors?
No. The CSS minifier strips comments, collapses whitespace, removes the trailing `;` before `}`, and drops spaces around punctuation (`{`, `}`, `:`, `;`, `,`, `>`, `+`, `~`). All selectors, properties, values, and at-rules are preserved exactly. The result is semantically identical and typically 20–30% smaller than the input.
Will minified code still work in older browsers?
The minifier preserves your input's syntax — it does not transpile. If your JavaScript uses modern syntax (optional chaining, top-level await, private class fields), the minified output uses the same modern syntax. To target older browsers, run Babel or esbuild as a transpile step BEFORE minifying. The order is: transpile, then minify. Reversing it loses the transpile's benefits.
Is the input sent to a server?
No. `js-beautify` and the CSS/HTML minifiers ship in the page bundle. `terser` is lazy-loaded from your own origin when you click Minify on JavaScript. No source code is ever transmitted to any server. You can verify in DevTools — the only network request is fetching the terser chunk from `/` on first JS-minify click.