mrkeyoor.com_
Sun 20 Sept 15:53 UTC
npmWeb Frontendupdated 20 Sept 2026

clean-css review

clean-css 5.3.3 is a Node CSS optimizer whose main API accepts source text or file paths and returns compressed CSS, warnings, errors, source-map output, and before-and-after byte statistics. Its default level 1 pass shortens values and declarations. Level 2 can restructure a stylesheet by merging selectors and moving declarations, which makes cascade testing part of adoption. Version 5.3 added `variableValueOptimizers`, a way to run named value optimizers such as `color` and `fraction` inside custom properties. We found a small CommonJS install, but the README now puts the project in maintenance mode.

Verdict

clean-css 5.3.3 installed in 0.4 seconds and occupied 2 MB in our sandbox, but its README says maintenance mode and our browser bundle failed. Keep it where established Node builds depend on its output; start new CSS pipelines with an actively released alternative.

We installed it

Lab card: what happened when we installed clean-cssScreenshot of clean-css documentation
Install✓ · 0.4s2 packages on disk · 2 MB
ImportESM import works · require() works · CommonJS package
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 clean-css install cleanly?

Yes. In a fresh container with an empty cache, npm install clean-css finished in 0.4s, leaving 2 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

Can clean-css 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 clean-css work with both ESM and CommonJS?

Yes. Both import 'clean-css' and require('clean-css') worked in Node 22 in our run. The package is published as CommonJS.

Does clean-css include TypeScript types?

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

clean-css or lightningcss: which should you use?

Pick lightningcss when current CSS syntax, prefixing, and fast native transforms matter more than matching clean-css output. clean-css 5.3.3 installed in 0.4 seconds and occupied 2 MB in our sandbox, but its README says maintenance mode and our browser bundle failed.

When should you not use clean-css?

New CSS syntax support needs an active release cadence. The README calls clean-css maintenance-only, and 5.3.3 has remained the current npm release since November 2023.

API stability4/5Version 5 still centers on `new CleanCSS(options).minify(input)`, with string, file-list, callback, and promise forms documented in the README. The 5.3 release added `variableValueOptimizers` within the existing level 1 options rather than replacing that contract. The same README declares maintenance mode, so the stable surface also reflects very little new release activity since 5.3.3.
Docs4/5The README names every constructor default and gives separate examples for level 1, level 2, batching, imports, rebasing, source maps, compatibility flags, and promise execution. Its FAQ explains two easy-to-miss behaviors: remote imports require asynchronous execution, and parse problems appear in result arrays. Plugin authors get less help because the useful property-object examples live in tests and optimizer source.
Maintenance1/5GitHub shows an unarchived repository last pushed on October 18, 2024, with 45 open issues and pull requests. npm still marks 5.3.3, published in November 2023, as latest. More important than either date, the maintainer states in the README that the project is in maintenance mode and promises only occasional bug-fix releases, which is a weak position for tracking new CSS syntax.
Ecosystem4/5npm counted 22,432,605 downloads from August 19 through August 25, 2026, and GitHub reports 4,200 stars. The README links integrations for webpack, Gulp, Grunt, Broccoli, Brunch, and PostCSS, so existing build-tool coverage is broad. New TypeScript and ESM projects get fewer conveniences because 5.3.3 has no declarations or exports map, and its CLI requires another package.

Use it if

  • A mature Node asset build already expects clean-css output and changing compressors would require a full visual regression pass
  • Your stylesheet benefits from opt-in level 2 passes such as duplicate-rule removal, non-adjacent selector merging, and shorthand compaction
  • One build step must inline local `@import` files, rebase relative `url()` references, and produce a source map
  • You need a synchronous minifier API and will fail the build when its result contains warnings or errors
Skip it if

Setup reality

We installed clean-css 5.3.3 in an uncached Node 22 container in 0.4 seconds. The result was 2 packages and 2 MB on disk; npm audit returned 0 known vulnerabilities. The package itself has one direct dependency, no peers, and 912 KB unpacked. require() and ESM import both loaded its CommonJS entry. It has no exports map and no bundled TypeScript types.

No account, environment variable, or config file is required. Input shape does matter: one string means CSS text, but an array of strings means file names. Version 5 leaves URL rebasing disabled unless you turn it on or provide rebaseTo. Local @import files are eligible for inlining by default; remote imports stay untouched unless their hosts are allowed.

The usual minify() path blocks until it finishes. Promise mode requires returnPromise: true, while callback mode is also available. Remote import loading needs one of those asynchronous forms. Allowing a network stylesheet into a build makes the output depend on that host, so restrict inline to named domains and set inlineTimeout rather than accepting arbitrary URLs.

Our browser bundle attempt with esbuild failed. Keep 5.3.3 in the Node build process. Also inspect result.errors and result.warnings: malformed input can be removed while the rest of the CSS is still returned. Level 2 is off by default because it can merge separated rules and relocate declarations. Enable individual passes first, then compare rendered pages that rely on ordering or old browser hacks.

Patterns

Compress an in-memory stylesheet minify-css-string

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

const result = new CleanCSS().minify('a { color: blue; margin: 0px; }');
if (result.errors.length || result.warnings.length) {
  throw new Error([...result.errors, ...result.warnings].join('\n'));
}
console.log(result.styles);

One string is parsed as CSS, not as a path. Version 5 may return partial output for bad input, so make both diagnostic arrays fatal in a build.

Turn on level 2 restructuring enable-level-two

const result = new CleanCSS({ level: 2 }).minify(css);

`level: 2` includes level 1 work. Its cross-rule moves can affect order-sensitive CSS, so compare rendered output before adopting it.

Limit the enabled optimizer passes select-optimizations

const result = new CleanCSS({
  level: {
    1: { all: true, normalizeUrls: false },
    2: { all: false, removeDuplicateRules: true }
  }
}).minify(css);

The `all` switch is applied before named overrides. This example retains URL spelling while enabling only duplicate-rule removal at level 2.

Shorten selected custom-property values optimize-css-variables

const result = new CleanCSS({
  level: {
    1: { variableValueOptimizers: ['color', 'fraction'] }
  }
}).minify(':root { --brand: rgb(255, 0, 0); --ratio: 0.50; }');

Version 5.3 introduced `variableValueOptimizers`. List only value categories that match how each custom property is consumed.

Combine stylesheet files and rebase URLs minify-css-files

const result = new CleanCSS({ rebaseTo: 'dist' })
  .minify(['src/base.css', 'src/theme.css']);

A string array is interpreted as file paths. `rebaseTo` should name the output directory so relative assets still resolve after concatenation.

Return separate results for each file process-files-separately

const results = new CleanCSS({ batch: true })
  .minify(['src/a.css', 'src/b.css']);

console.log(results['src/a.css'].styles);

Batch mode changes the result shape to an object keyed by input name; it does not concatenate the two files.

Use the promise execution path use-promise-api

const result = await new CleanCSS({ returnPromise: true }).minify(css);
if (result.errors.length) throw new Error(result.errors.join('\n'));

Version 5 runs synchronously unless `returnPromise` is set or a callback is supplied.

Fetch an import from one approved host inline-remote-import

new CleanCSS({
  inline: ['local', 'styles.example.com'],
  inlineTimeout: 3000
}).minify(css, (error, result) => {
  if (error) throw error;
  console.log(result.styles);
});

Remote `@import` loading works only asynchronously. A hostname allowlist keeps arbitrary CSS URLs out of the build.

Persist minified CSS and its map emit-source-map

const result = new CleanCSS({
  sourceMap: true,
  rebaseTo: 'dist'
}).minify(['src/app.css']);

await fs.promises.writeFile('dist/app.min.css', result.styles);
await fs.promises.writeFile('dist/app.min.css.map', result.sourceMap.toString());

`result.sourceMap` is a generator, not ready-to-write text. Call `toString()` before saving the map file.

Protect one block from rewriting preserve-css-block

/* clean-css ignore:start */
.legacy-widget { color: transparent; }
/* clean-css ignore:end */

The paired clean-css comments preserve the enclosed bytes while optimization continues around them.

Register an application-specific unit allow-custom-unit

const result = new CleanCSS({
  compatibility: { customUnits: { rpx: true } }
}).minify('.tile { width: 20rpx; }');

The compatibility map tells 5.3.3 that `rpx` is valid; otherwise an unknown unit may cause the declaration to be removed.

Format compressed output for review format-readable-css

const result = new CleanCSS({
  format: { breaks: { afterRuleEnds: 1 }, indentBy: 2, indentWith: 'space' }
}).minify(css);

Formatting adds whitespace after optimization. Use it when generated CSS is committed and humans need readable diffs.

Alternatives

PackageRegistryPick it when
lightningcssnpmPick it when current CSS syntax, prefixing, and fast native transforms matter more than matching clean-css output.
cssnanonpmPick it when PostCSS is already the parser and plugin host for the project.
esbuildnpmPick it when esbuild already bundles the application and basic CSS minification is enough.
cssonpmPick it for structural compression based on css-tree and compare its restructuring against your visual tests.

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.