Is minifying CSS and HTML still worth it?
Minification removes characters; compression encodes repetition. Because gzip and brotli already handle repeated whitespace efficiently, minifying before compressing typically saves far less than the raw character count suggests — often only a few percent.
Updated 2026-08-24
Minification and compression are different things
These are routinely discussed as if they were the same optimisation, and the distinction explains why minification saves less than people expect.
Minification is a source transformation. It removes characters that a parser does not need — whitespace, comments, optional punctuation — and produces a smaller but equivalent file. It happens once, at build time, and the result is what sits on disk.
Compression is an encoding applied in transit. Gzip and brotli find repeated sequences and replace them with references to earlier occurrences, and the browser reverses this before parsing. It happens per request, though a static host usually caches the compressed form.
The interaction is the important part. Repeated whitespace is the single most compressible thing in a text file — four spaces of indentation appearing ten thousand times costs almost nothing after compression, because it is one pattern referenced repeatedly. So the bytes a minifier removes are largely bytes compression was already handling nearly for free.
The measured result is that minifying a stylesheet might cut its raw size by a fifth to a third, and cut its compressed size by only a few percent. That is still worth having, because compressed size is what actually crosses the network and a few percent of a large stylesheet is real. But it reorders the priorities: shipping less code matters enormously, and minifying the code you ship matters modestly. A build that removes an unused dependency saves more than a build that perfectly minifies one that stayed.
The corollary is that a file served without compression is the actual problem. If a host is not sending brotli or gzip for text assets, fixing that is worth several times more than any minification, and it is a configuration change rather than a build step.
What a CSS minifier is allowed to do
CSS is comfortable to minify because its grammar is regular and whitespace is almost never significant.
The safe removals are whitespace around braces, colons and semicolons, the final semicolon in a block, comments, and the leading zero in a decimal below one. Beyond that, minifiers normalise values: a zero length loses its unit because zero pixels and zero ems are identical, colours collapse to their shortest form so white becomes fff, and long hex values reduce to three digits where the pairs repeat.
More aggressive minifiers merge and reorder. Two rules with identical selectors combine, two selectors with identical declarations combine, and later declarations that override earlier ones in the same block can be dropped. These are correct transformations under the cascade and they are where a minifier earns most of its saving on a large stylesheet.
Two things are not safe to touch and good minifiers know it. Custom property values are preserved verbatim, because their content is not parsed as CSS until it is substituted — a value that looks like it has redundant whitespace may be used somewhere that whitespace matters. And whitespace inside a content string or a url is part of the value rather than formatting.
The remaining trap is source ordering across files. Merging rules is safe within a stylesheet and can change behaviour if a minifier is given several files concatenated in an order that a build later changes. Minify the final concatenation, not the parts.
HTML whitespace is not always safe to remove
HTML is where minification stops being mechanical, because whitespace in HTML sometimes renders.
The core issue is inline layout. In a line of inline or inline-block elements, whitespace between them collapses to a single rendered space — but it does not disappear. Remove the newline between two inline-block elements and they move flush against each other, changing the layout by the width of a space. This is the classic gap that people fight with negative margins and font-size zero, and a minifier deleting it is a visual change rather than an optimisation.
Several elements preserve whitespace entirely. Content inside a pre element, or anything with white-space set to pre or pre-wrap, renders exactly as written, so a minifier collapsing it destroys code samples and formatted output. Textarea content is the same: the whitespace inside it is the initial value of the field.
Attribute quotes are the other tempting removal. The specification permits unquoted attribute values in limited cases, and dropping quotes saves two characters per attribute. It is safe only when the value contains no whitespace, quotes, angle brackets or equals signs, and it makes the output far harder to read and to diff. The saving after compression is negligible.
The conservative settings are therefore the right ones for HTML: collapse runs of whitespace to a single character rather than removing it, respect preserved-whitespace elements, keep attribute quotes, and remove comments except any that are functionally significant. Aggressive HTML minification is one of the few build optimisations that reliably produces visual bugs, and it buys the least of any of them.
Formatting is the opposite operation and matters more often
Running a file through a formatter expands it, and for anything a person has to read that is the more valuable transformation.
The strongest argument is diffing. Version control compares lines, so a file with consistent line breaks produces diffs that show what changed. A minified file is one enormous line, so any change reports the whole file as modified and code review becomes impossible. The same applies to a formatted file whose formatting is inconsistent: half of every diff is whitespace churn, and the real change hides inside it.
SQL is the clearest case. A query written as a single line is readable at twenty characters and opaque at two hundred, and long queries are exactly where mistakes live. Formatting one so that each clause starts on its own line and joins and conditions align makes an incorrect join condition or a missing predicate visible rather than buried. This is a correctness benefit, not a cosmetic one.
XML and JSON benefit similarly, with an additional use: formatting is how you confirm structure matches intent. Nesting that is wrong is nearly invisible in a compact document and obvious in an indented one, and a formatter that fails to parse a document has told you something useful before you read a line of it.
The sensible arrangement is that formatted source is what humans and version control see, and minification happens at build time on the way out. Committing minified assets puts the unreadable version under review and the readable version nowhere, which is exactly backwards.