Everyone says "minify your CSS." Almost nobody says how much it actually helps, especially if your server already compresses files.
So I ran the numbers instead of repeating the advice. Some of the results changed how I think about it.
First, what does a minifier actually do?
It rewrites your CSS into a smaller but equivalent form: no comments, no whitespace, shorter values. Here's a deliberately messy stylesheet I used to test three popular minifiers (419 bytes):
/* Card component */
.card {
margin: 0px;
padding: 16px 16px 16px 16px;
background-color: #ffffff;
color: rgba(0, 0, 0, 1);
border: 1px solid #cccccc;
}
.card-title { font-weight: bold; margin: 0px; }
.card:hover { background-color: #f5f5f5; }
.card-title { font-size: 1.25rem; }
.btn { color: #ffffff; background-color: #0066ff; }
.btn-alt { color: #ffffff; background-color: #0066ff; }
And what cssnano produced (234 bytes, about 44% smaller):
.card{margin:0;padding:16px;background-color:#fff;color:#000;border:1px solid #ccc}.card-title{font-weight:700;margin:0}.card:hover{background-color:#f5f5f5}.card-title{font-size:1.25rem}.btn,.btn-alt{color:#fff;background-color:#06f}
Look at what happened beyond whitespace:
-
0pxbecame0 -
padding: 16px 16px 16px 16pxbecame16px -
#ffffffbecame#fff, andrgba(0,0,0,1)became#000 -
boldbecame700 -
.btnand.btn-altwere merged into one rule
Lightning CSS gave the same size (234 bytes). clean-css at its defaults gave 282 bytes: it left padding: 16px 16px 16px 16px alone and kept .btn and .btn-alt separate. So minifiers aren't identical.
Also notice the two .card-title rules weren't merged by any tool. That's on purpose. Lightning CSS's docs explain it only merges adjacent rules, because merging others could change the cascade order and break styles. Good minifiers are conservative about anything that could change behavior.
The benchmark: Bootstrap through 3 minifiers
Toy examples are fun, but let's use a real stylesheet. I took the unminified bootstrap.css from Bootstrap 5.3.3 (281,005 bytes) and ran it through three minifiers (cssnano 8.0.10, Lightning CSS 1.33.0, clean-css 5.6.3). Then I measured raw size, gzip (level 9) and Brotli (quality 11):
| Raw | gzip | Brotli | |
|---|---|---|---|
| Original | 281,005 B | 32,807 B | 24,509 B |
| cssnano | 231,970 B (−17.5%) | 30,975 B (−5.6%) | 22,984 B (−6.2%) |
| Lightning CSS | 229,303 B (−18.4%) | 30,580 B (−6.8%) | 22,650 B (−7.6%) |
| clean-css | 232,757 B (−17.2%) | 30,800 B (−6.1%) | 22,750 B (−7.2%) |
What the numbers say
1. Minification alone: about 17-18% smaller. Solid, and nearly free.
2. Compression is the real hero. Gzip alone shrinks the original file by about 88%, and Brotli by about 91%. Minification alone gets you 17%. If your server isn't compressing text, fix that first.
3. On top of compression, minification saves roughly 1.5-2.2 KB here. That's a smaller win than the raw numbers suggest, because gzip and Brotli already crush repeated whitespace and indentation. The gain is real but modest.
4. The three tools landed within about 1.5 percentage points of each other on this file. Pick based on your stack, not on a tiny size difference.
Caveats: this is one file, and Bootstrap's source is already tidy. Messier CSS (lots of comments, duplicated rules) will shrink more. I also used max compression levels; many servers use lower ones, so real-world differences can be a bit larger.
So is it worth it? Yes, and here's when it matters most
- Servers/hosts without compression. Raw size is what users download, and here minification saves about 50 KB on this file.
- Places where compression doesn't apply, like some email setups and embedded snippets.
- Free wins add up. 2 KB on a stylesheet is small, but you get it with zero code changes.
- Cleaner output for free, like merged rules and shortened values, without touching your source.
The takeaway: minify and compress, but don't expect miracles from minification alone. If you want to understand why this matters for performance, Chrome's Lighthouse docs on minifying CSS walk through it. They also note that Lighthouse's savings estimate is conservative, since real minifiers do smarter optimizations than just stripping whitespace.
How to minify: two paths
The quick path (no setup). Working on a small site, a client fix, or a one-off file? Paste your CSS into a free online CSS minifier, copy the result, done. It's also a handy way to sanity-check how much a file would shrink before you decide to automate anything.
The automated path. For real projects, put it in your build so you never forget:
- Modern tools like Vite, Parcel, Next.js and others minify CSS in production builds (check your version's docs for the exact defaults)
- webpack needs a plugin like
css-minimizer-webpack-pluginfor this - Or run a CLI yourself with PostCSS + cssnano, Lightning CSS, or clean-css
A PostCSS + cssnano one-liner:
npx postcss input.css -u cssnano --no-map -o output.min.css
Don't skip these gotchas
Keep source maps on. Debugging a one-line CSS file is miserable. Both Lightning CSS (--sourcemap) and clean-css (--source-map) can generate one, so DevTools shows your original code.
Never edit the minified file. Keep styles.css as the source of truth and generate styles.min.css from it.
Test after changing your setup. Minifiers are safe by design, but tools differ. In my demo, Lightning CSS even reordered independent declarations (harmless there). Give the site a quick visual check.
Watch your browser targets. Some tools (Lightning CSS especially) can transform modern syntax based on your target browsers, so check your config.
Try it yourself in 2 minutes
Don't trust my numbers, reproduce them:
mkdir css-bench && cd css-bench && npm init -y
npm i bootstrap@5.3.3 cssnano postcss postcss-cli lightningcss-cli clean-css-cli
sed '/sourceMappingURL/d' node_modules/bootstrap/dist/css/bootstrap.css > orig.css
npx postcss orig.css -u cssnano --no-map -o cssnano.min.css
npx lightningcss --minify orig.css -o lightning.min.css
npx cleancss -o cleancss.min.css orig.css
for f in orig cssnano.min lightning.min cleancss.min; do
echo "$f: raw=$(wc -c < $f.css) gzip=$(gzip -9 -c $f.css | wc -c)"
done
Even better, run your own stylesheet through it and compare. You can also drop it into the online minifier and see how it stacks up. Then open DevTools → Network, and check the content-encoding header to confirm your server is compressing (br or gzip).
Quick checklist
- [ ] Production build outputs minified CSS
- [ ] Gzip or Brotli is enabled (this is the bigger win!)
- [ ] Source maps are on if you need production debugging
- [ ] Source CSS stays readable in your repo
- [ ] You did a quick visual check after changing the setup
Wrapping up
CSS minification won't transform your site by itself, but it's a free, low-risk improvement, and it works best alongside compression. Now you have real numbers to back it up.
What's your setup: cssnano, Lightning CSS, or whatever your bundler ships? And did you get different results on your own CSS? Tell me in the comments. 👇
Top comments (1)
If you're not TOO "size concerned" then it might be a viable option to only go for compression, and skip minification - at least you don't need to deal with source maps ...