mrkeyoor.com_
Sun 20 Sept 12:44 UTC
npmWeb Frontendupdated 20 Sept 2026

cssnano review

cssnano 8 is a production-time CSS minifier built as a PostCSS plugin. Its default preset runs separate optimizers for comments, colors, selectors, values, duplicate rules, and other CSS syntax while aiming to keep the rendered result unchanged. The advanced preset makes assumptions about seeing the complete stylesheet set, so it needs more caution around third-party or runtime CSS. Version 8.0.9 updates colordx and SVGO to pick up their latest fixes; 8.0.8 had corrected gradient shortening to use the specification algorithm. Our browser build failed on Node-only code, which confirms that cssnano belongs in the build process rather than application code.

Verdict

cssnano 8.0.8 took 5.7 seconds and 21 MB across 67 installed packages in our sandbox, with 0 audit findings, so its cost makes sense mainly inside an existing PostCSS production build. Use the default preset first; reach for a standalone compiler when PostCSS-specific control is not part of the requirement.

We installed it

Lab card: what happened when we installed cssnanoScreenshot of cssnano documentation
Install✓ · 5.7s67 packages on disk · 21 MB
ImportESM import works · require() works · CommonJS package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
Typesno TypeScript types found
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does cssnano install cleanly?

Yes. In a fresh container with an empty cache, npm install cssnano finished in 6 seconds, leaving 67 packages and 21 MB on disk. npm audit reported no known vulnerabilities.

Can cssnano run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does cssnano work with both ESM and CommonJS?

Yes. Both import 'cssnano' and require('cssnano') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does cssnano include TypeScript types?

No type declarations were found in our install, so TypeScript users need their own declarations.

cssnano or lightningcss: which should you use?

lightningcss: Choose it for a Node 22 build that values native-speed minification and syntax lowering in one compiler. cssnano 8.0.8 took 5.7 seconds and 21 MB across 67 installed packages in our sandbox, with 0 audit findings, so its cost makes sense mainly inside an existing PostCSS production build.

When should you not use cssnano?

Your build is pinned to Node 20; cssnano 8 accepts Node ^22.11.0, ^24.11.0, or 26+ only

API stability4/5cssnano 8 keeps the established PostCSS plugin call and preset tuple, so ordinary configuration remains recognizable. The major release still changed the operating boundary by dropping older Node versions and removing declaration sorting from the default preset. Patch 8.0.8 changed gradient output for standards correctness, and 8.0.9 updated optimizer dependencies, which makes snapshot review prudent even when the API call itself stays fixed.
Docs4/5The cssnano site documents installation, config-file lookup, presets, every optimization, and an online playground that shows emitted CSS. It also separates default-preset guarantees from advanced-preset assumptions. Debugging one changed declaration can still require moving between the preset page and an individual PostCSS optimizer package, so the docs explain the system better than they provide a single diagnostic path.
Maintenance5/5GitHub recorded a push on 2026-08-26, an 8.0.9 release on 2026-08-25, and 56 open items counted together as issues and pull requests. The preceding releases fixed gradient math, cascade-layer handling, invalid rule merges, grid-template-area damage, selector shortening, and shorthand behavior. That recent sequence shows active CSS correctness work, with the tradeoff that emitted output can move in patch releases.
Ecosystem5/5npm counted 19,077,540 cssnano downloads from 2026-08-19 through 2026-08-25, and GitHub reported 4,975 stars. The package is designed for PostCSS and its individual optimizers are published as separate modules, which gives existing PostCSS stacks many integration paths. Our 8.0.8 install also loaded through both CommonJS require() and ESM import despite the package itself being CommonJS.

Use it if

  • Your Node 22.11+ build already uses PostCSS and you want minification to operate on the same parsed CSS tree
  • A particular rewrite needs to be disabled or configured while the rest of the default preset stays active
  • Browserslist targets should influence optimizers that can emit different CSS for different browser sets
  • You maintain output fixtures and can inspect stylesheet changes after cssnano patch upgrades
Skip it if

Setup reality

Our install of cssnano 8.0.8 completed in 5.7 seconds in a clean Node 22 container. The install left 67 packages occupying 21 MB, while npm audit reported 0 known vulnerabilities. The published package declared 2 direct dependencies and 1 PostCSS peer, and its own unpacked files measured 40 KB. We found no TypeScript types in that measured package. The How we test method used an unprivileged container with no package cache.

The measured 8.0.8 entry was CommonJS behind an exports map, and both require() and ESM import loaded it. A browser bundle did not compile because the dependency path uses Node-only code. Version 8 also has a tight engine rule: Node ^22.11.0, ^24.11.0, or 26+. CI images on Node 20 must move first, even if the existing PostCSS setup still starts there.

Install PostCSS beside cssnano because it is a peer dependency. Put cssnano after plugins whose generated output should be compressed. An inline preset takes precedence over config discovery, so do not pass one while expecting cssnano.config.js to supply different options. PostCSS owns source-map input and output; cssnano does not repair missing from, to, or previous-map settings. Version 8.0.9 updates colordx and SVGO rather than changing this configuration contract.

The default preset is the sensible first run. The separately installed advanced preset may rewrite identifiers or remove declarations based on a whole-project view. Test pages that mix 2 or more bundles, embedded widgets, and styles inserted by JavaScript before enabling it. Keep a before-and-after CSS fixture for every disabled optimizer, since patch releases such as 8.0.8 can deliberately change emitted gradients without altering your config file.

Patterns

Minify at the end of a PostCSS chain configure-postcss

// postcss.config.cjs
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano')({ preset: 'default' }),
  ],
};

cssnano 8 requires Node 22.11+ and a compatible PostCSS peer. Run generators and prefixing before the minifier.

Keep development CSS readable limit-to-production

// postcss.config.cjs
const plugins = [require('autoprefixer')];
if (process.env.NODE_ENV === 'production') {
  plugins.push(require('cssnano')({ preset: 'default' }));
}
module.exports = { plugins };

A single NODE_ENV check keeps local rebuilds readable while CI and local production builds use the same 1 preset.

Move preset choices into cssnano.config.js use-config-file

// cssnano.config.js
module.exports = {
  preset: ['default', { discardComments: { removeAll: true } }],
};

// postcss.config.cjs
module.exports = { plugins: [require('cssnano')()] };

Call cssnano with no inline preset when using this file. An inline preset prevents the separate config from supplying those options.

Turn off one unsafe rewrite disable-transform

require('cssnano')({
  preset: ['default', {
    mergeRules: false,
    convertValues: { length: false },
  }],
});

Use false to remove a preset plugin and an object to configure one. Preserve the CSS case that exposed the problem as a regression fixture.

Retain bang comments keep-license-comments

require('cssnano')({
  preset: ['default', {
    discardComments: { remove: (text) => !text.startsWith('!') },
  }],
});

This keeps comments beginning with !. Check the actual license terms before deleting every notice from a distributed asset.

Run cssnano from a Node script process-css-string

const postcss = require('postcss');
const cssnano = require('cssnano');

const result = await postcss([cssnano({ preset: 'default' })])
  .process(sourceCss, { from: 'src/site.css', to: 'dist/site.css' });
await fs.promises.writeFile('dist/site.css', result.css);

PostCSS processing is asynchronous. Await the result and provide from and to so warnings and map paths refer to real files.

Carry an upstream source map emit-source-map

const result = await postcss([cssnano()]).process(sourceCss, {
  from: 'build/site.css',
  to: 'public/site.css',
  map: { inline: false, prev: upstreamMap },
});
await fs.promises.writeFile('public/site.css.map', result.map.toString());

PostCSS owns the 2 map stages. Without prev, the final map points to the intermediate CSS rather than its original sources.

Skip optimization of embedded SVG protect-svg-urls

require('cssnano')({
  preset: ['default', { svgo: false }],
});

The SVGO optimizer can change SVG stored inside CSS url() values. Disable it when a reproduced icon or mask regression points to that pass.

Use the advanced preset with exclusions try-advanced-preset

// npm install cssnano-preset-advanced
require('cssnano')({
  preset: ['advanced', { zindex: false, discardUnused: { fontFace: false } }],
});

The advanced preset is a separate package. Test all CSS bundles together because identifier and unused-value rewrites can miss runtime or vendor styles.

Pass cssnano options through webpack configure-webpack-minifier

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = { optimization: { minimizer: ['...', new CssMinimizerPlugin({
  minimizerOptions: { preset: ['default', { svgo: false }] },
})] } };

css-minimizer-webpack-plugin uses cssnano by default. Avoid a second cssnano pass in postcss-loader for the same final asset.

Alternatives

PackageRegistryPick it when
lightningcssnpmChoose it for a Node 22 build that values native-speed minification and syntax lowering in one compiler
cssonpmChoose it when one standalone CSS optimizer is preferable to a PostCSS peer and preset chain
clean-cssnpmChoose it when its level 1 and level 2 controls already match an established Node asset pipeline

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.