All Tools / Blog / How to Minify CSS for Production

How to Minify CSS for Production

3 min read

CSS minification removes whitespace, comments, and redundant syntax to reduce file size without changing any visual behaviour. A typical stylesheet might shrink from 80 KB to 55 KB — a 30% reduction that costs nothing but a build step.

What minification does

A minifier converts this:

/* Button styles */
.button {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    background-color: #3b82f6;
    color: #ffffff;
    border-radius: 4px;
    font-size: 14px;
}

.button:hover {
    background-color: #2563eb;
}

Into this:

.button{display:inline-flex;align-items:center;padding:8px 16px;background-color:#3b82f6;color:#fff;border-radius:4px;font-size:14px}.button:hover{background-color:#2563eb}

Specifically: removes whitespace, newlines, and comments; shortens #ffffff to #fff; removes the last semicolon before }; removes spaces around colons and brackets.

More advanced minifiers also merge duplicate selectors, remove vendor prefixes no longer needed, and optimize 0px to 0.

Method 1: PostCSS + cssnano (the standard build tool approach)

If you're using a build tool (webpack, Vite, Parcel, Rollup), cssnano is the most widely used CSS minifier:

npm install --save-dev postcss cssnano

postcss.config.js:

module.exports = {
    plugins: [
        require('cssnano')({ preset: 'default' }),
    ],
};

In Vite this happens automatically in production builds via the built-in CSS pipeline. In webpack:

// webpack.config.js
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
    optimization: {
        minimizer: [new CssMinimizerPlugin()],
    },
};

Method 2: LightningCSS (fastest)

LightningCSS is a Rust-based CSS parser, transformer, and minifier. It's significantly faster than cssnano and handles modern CSS features:

npm install --save-dev lightningcss-cli
# Minify a single file
npx lightningcss --minify --bundle styles.css -o styles.min.css

# With browser targets
npx lightningcss --minify --targets '>= 0.25%' styles.css -o styles.min.css

Vite 4+ uses LightningCSS by default. If you're starting a new project, it's the recommended choice.

Method 3: clean-css (Node.js API)

npm install clean-css-cli
# CLI
npx cleancss -o styles.min.css styles.css

# With source map
npx cleancss -o styles.min.css --source-map styles.css

As a Node.js API:

const CleanCSS = require('clean-css');
const fs = require('fs');

const input = fs.readFileSync('styles.css', 'utf8');
const output = new CleanCSS({ level: 2 }).minify(input);
fs.writeFileSync('styles.min.css', output.styles);
console.log(`Reduced from ${input.length} to ${output.styles.length} bytes`);

Level 1 does safe transformations (whitespace, comments). Level 2 merges rules and does more aggressive optimizations — test your output carefully at level 2.

Method 4: Python (css-html-js-minify)

pip install css-html-js-minify
from css_html_js_minify import css_minify

with open('styles.css', 'r') as f:
    css = f.read()

minified = css_minify(css)
with open('styles.min.css', 'w') as f:
    f.write(minified)

Or from the command line:

css-html-js-minify styles.css
# outputs styles.min.css

Gzip / Brotli compression on top

Minification and compression work on different things:

  • Minification removes unnecessary characters — the output file is smaller.
  • Gzip/Brotli exploits repetition in the file to compress it further.

Both together give the best results. Minification actually helps compression: removing variable names and whitespace increases the density of meaningful tokens, giving the compressor more repetition to work with.

On nginx:

gzip on;
gzip_types text/css;
gzip_min_length 256;

Typical final sizes for a 100 KB stylesheet:

Step Size
Original 100 KB
After minification ~65 KB
After gzip ~15 KB
After brotli ~12 KB

Source maps

Always generate source maps in development so DevTools shows the original CSS lines when debugging:

npx lightningcss --minify --source-map styles.css -o styles.min.css

In production, source maps are optional — they can be served at a separate URL so end-users don't load them, but your team can still debug.

Key takeaways

  • cssnano (PostCSS) and LightningCSS are the standard options for build-tool pipelines.
  • LightningCSS is faster and handles modern CSS — prefer it for new projects.
  • Level 2 minification (merging rules) is more aggressive; test the output before deploying.
  • Minification + gzip typically reduces a stylesheet to 10–15% of its original size.
  • Always generate source maps so you can debug in DevTools without the minified output.