tooldura

Developer Tools

Minifying CSS Saves Almost Nothing, Until You Delete the Comments

T
tooldura editorial
8 min readUpdated August 22, 2026Open tool →

Every minifier advertises the same number: your stylesheet got 30% smaller. That number is measured on the raw file, and the raw file is not what anybody downloads. Once gzip is in the path, removing all the indentation from a stylesheet saves about four percent. Removing the comments can save fifty.

The Same Files, Measured Both Ways

Three real stylesheets, each run through two passes: one that removes only whitespace, and one that also removes comments. Everything is measured as it would be served, with gzip at level 9.

The pattern holds across all three. Whitespace is nearly free once it is compressed, because gzip's whole job is spotting repeated sequences and a stylesheet's indentation is the most repetitive thing in the file. Comments are not repetitive. They are unique prose, they compress about as badly as text ever does, and they are the only part of a stylesheet with no effect on rendering at all.

What Each Pass Is Worth After Compression

Gzipped sizes. The percentage is the saving against the gzipped original, not the raw file.

StylesheetWhitespace onlyWhitespace and comments
This site's globals.css, 8.9 kB−4.4%−28.2%
Tailwind theme.css, 19.5 kB−4.7%−5.0%
Tailwind preflight.css, 8.4 kB−3.3%−58.2%

Why preflight.css Loses Sixty Percent and theme.css Loses Five

Tailwind's preflight.css is a reset, and a reset is mostly argument. Almost every rule in it carries a comment explaining which browser bug it exists for and what breaks if you remove it. Strip those and well over half the compressed file goes with them.

theme.css in the same package is a list of custom properties: hundreds of lines of --color-red-500: oklch(…). There is barely a comment in it, and the lines are so similar to each other that gzip already encodes them at close to nothing. Minifying it is very nearly a waste of a build step.

That is the useful shape of the rule. The compressed saving from minification tracks how much of your file is prose, not how much of it is formatting. A stylesheet written by hand with a paragraph above every section has a lot to gain. A generated one has almost none, which is why the CSS your build tool emits is already minified and re-minifying it changes nothing.

⚠️

Three spaces that are not decoration

calc(100% - 20px) needs the spaces around the minus; without them the -20px is read as a single negative number and the expression is invalid. a :hover with a space is a descendant selector and a:hover without one is not, so a minifier that strips before every colon silently retargets your rule. And @media screen and (min-width: 640px) cannot become and(min-width:640px), because and( tokenizes as a function. All three are ordinary CSS, and all three are how a naive find-and-replace minifier corrupts a file.

Why This Cannot Be Done With Regular Expressions

The instinct is to reach for a couple of replacements: kill /\*.*?\*/, collapse \s+, done. It falls over on the first real stylesheet.

A comment marker inside a string is not a comment: content: "/*" is a valid declaration. A semicolon inside a url() is not the end of a declaration, and every data URI has one, right there in url(data:image/svg+xml;base64,…). A brace inside a content string is not the end of a block. Each of these needs the file to be read as tokens rather than as text, which is what CSS Syntax Module Level 3 specifies: comments, strings and url tokens are consumed whole before anything else looks at them.

There is one more trap that only shows up once the tokenizer is right. A comment is not nothing; it separates tokens. width:100px/**/; is the old IE hack and removing the comment is free, but in foo/*x*/bar the comment is the only thing keeping two identifiers apart, and deleting it outright fuses them into foobar. The safe move is to replace a removed comment with a space and let the ordinary spacing rules decide whether that space can then go.

Minify a stylesheet, or read one back

Comments and whitespace out, structure untouched, with the before and after size.

Open CSS Minifier →

The Optimizations Worth Refusing

Past whitespace and comments, minifiers start rewriting meaning. Each of these is a real feature in some tool, and each has a failure mode that is invisible until production.

1

Removing duplicate declarations

`display:-webkit-box` followed by `display:flex` is not a duplicate, it is a fallback: the old browser takes the first and ignores the second, the new one takes the last. Deduplicating by property name deletes support for whichever browser you were propping up.

2

Merging rules with the same selector

Two blocks with the same selector can be separated by a third rule that overrides one of their properties. Pull them together and the cascade order changes underneath you.

3

Collapsing longhands into a shorthand

`margin-top` and `margin-bottom` are not `margin`. The shorthand also resets `margin-left` and `margin-right` to zero, which throws away whatever they inherited or were set to elsewhere.

4

Dropping units from zero

`0px` and `0` are interchangeable for a length, and they are not for everything: `<time>` and `<angle>` reject a bare zero, so `transition: all 0s` must keep its unit or the declaration is dropped. Flex is its own trap, where `flex-basis: 0` and `0px` differ in older implementations.

5

Reordering anything at all

The cascade is defined by document order for rules of equal specificity. Any reordering is a bet that nothing in the file relies on it, and the payoff is a handful of bytes that gzip would probably have found anyway.

What to Actually Do

Serve CSS compressed. This is the whole game and it is a server setting, not a build step: gzip takes a typical stylesheet to about a quarter of its size, and brotli beats it by another ten to fifteen percent. If compression is off, no amount of minification will make up the difference.

Then minify, mostly for the comments. Keep the /*! ones, which is the convention every major minifier honours for license headers that have to survive. If your CSS ships under MIT or Apache-2.0 and carries an attribution notice, that notice is a licensing obligation and not a comment you get to delete.

And stop measuring the raw file. The number that matters is what leaves the server, which you can see in the network panel under content-length with content-encoding: gzip beside it. A build step that reports 31% smaller while the wire sees 4% is not lying, it is just answering a question nobody asked.

Frequently Asked Questions

Related Tools

Keep Reading