induwara.lk
induwara.lkDeveloper · Browser-only

HTML, CSS & JavaScript Minifier — beautify and minify online

Minify or beautify HTML, CSS, and JavaScript in your browser. Tag-aware HTML, comment-stripping CSS, JSMin-safe JS — nothing is uploaded, no signup, sources cited below.

By Induwara AshinsanaUpdated May 11, 2026
HTML / CSS / JS Minifier
Runs in your browser
Language
Output
Indent

290 characters, 13 lines.

Idempotent — minifying the output produces the same bytes.

Status
Processed
Output is idempotent
Size change
-23.4%
290 → 222 bytes
Bytes saved
68
Vs. original input
Lines
13 → 1
Input → output

How it works

Each language gets a small, character-by-character state machine rather than a global regex pass. This matters because the three things that trip up naive minifiers — a `//` inside an HTML attribute or a CSS url(), a `:` inside a CSS string, a `/` that opens a JavaScript regex literal — all need surrounding context to be read correctly.

The HTML pass follows the same tag-vs-text tokenization the WHATWG parser uses. Standard <!-- ... --> comments are stripped; conditional comments (<!--[if IE]>…) and bang-prefixed comments are kept. Runs of whitespace inside text nodes collapse to a single space; whitespace flanking a tag boundary is dropped entirely. Anything inside <pre>, <textarea>, <script>, <style>, <code>, <svg>, or <math> is copied through byte-for-byte — those bodies are governed by another grammar.

The CSS pass follows CSS Syntax Module Level 3. The tokenizer recognises strings (single- and double-quoted) so a colon or comma inside one is never touched. Comments are stripped, except /*! … */ bangs — the convention every minifier respects for licence banners. Whitespace runs collapse, and the space adjacent to { } ; , : > ~ + is dropped. The last ; before a closing } goes too — it is optional by the spec.

The JavaScript passis Douglas Crockford's JSMin algorithm, lifted into TypeScript and extended to recognise ES2024 syntax: template literals (with ${expr} brace tracking), regex literals (disambiguated from division by inspecting the previous token), and Unicode identifiers. Whitespace is removed except where deleting it would either join two identifier characters (e.g. return foo must keep its space) or change semantics under automatic semicolon insertion. A bare return followed by a newline is preserved because ASI would otherwise insert a semicolon — collapsing the newline to a space changes what the function returns. Identifiers are never renamed and dead code is not removed, so stack traces and source maps remain meaningful.

Every successful run is cross-checked with an idempotency test: the engine minifies its own minified output and confirms it produces the same bytes. If the two ever differ, the page surfaces a warning under the output panel — a regression in the engine cannot ship unnoticed.

Worked examples

HTML · Minify a typical page

Input

<!DOCTYPE html>
<html>
  <!-- nav -->
  <body>
    Hello   World
  </body>
</html>

Output

<!DOCTYPE html><html><body>Hello World</body></html>

Comment stripped, whitespace inside the text node collapsed to one space, whitespace flanked by tag boundaries removed.

HTML · Preserve <pre> content byte-for-byte

Input

<pre>  keep   me  </pre>

Output

<pre>  keep   me  </pre>

Inside <pre>, <textarea>, <script>, <style>, <code>, <svg>, <math> nothing is touched — whitespace there is semantically meaningful.

CSS · Minify a stylesheet with comments and a trailing semicolon

Input

body {
  color: red;
  margin: 0px;
}
/* note */
.foo { padding: 10px; }

Output

body{color:red;margin:0px}.foo{padding:10px}

Comments stripped, whitespace removed around `{ } ; , :`, the last `;` before `}` dropped. /*! ... */ comments are preserved verbatim for licence banners.

JavaScript · Minify a function with comments

Input

function add(a, b) {
  // returns sum
  return a + b;
}

Output

function add(a,b){return a+b;}

Line comment stripped, whitespace removed except where two identifier characters would collide.

JavaScript · Recognise regex and string literals

Input

const re = /a\/b/g;
const s = "https://x/y";

Output

const re=/a\/b/g;const s="https://x/y";

After `=` the `/` opens a regex literal — its inner `/` is not read as a comment. Inside the string, the `//` is not read as a comment either.

JavaScript · Honour ASI on a bare `return` line

Input

function f() {
  return
  42;
}

Output

function f(){return
42;}

Automatic semicolon insertion would terminate at `return` on its own line. Collapsing the newline to a space would silently change the value the function returns, so the minifier preserves it.

Frequently asked questions

Sources & references

Implementation cross-checked against these specifications on 2026-05-11. The transforms run from pure state machines — there are no external library dependencies, so the algorithms above are the definitive description of what the engine does.

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.