autoprefixer vs cssnano vs postcss vs purify-css
CSS Optimization and Processing Tools
autoprefixercssnanopostcsspurify-cssSimilar Packages:

CSS Optimization and Processing Tools

postcss is a tool for transforming CSS with JavaScript plugins. autoprefixer and cssnano are popular PostCSS plugins that add vendor prefixes and minify CSS, respectively. purify-css is a standalone tool for removing unused CSS selectors, but it is officially deprecated and should not be used in new projects. These packages often work together in modern frontend build pipelines to optimize CSS for production.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
autoprefixer022,593199 kB412 days agoMIT
cssnano04,9577.37 kB1054 months agoMIT
postcss028,966204 kB288 months agoMIT
purify-css09,891-819 years agoMIT

CSS Optimization and Processing: autoprefixer, cssnano, postcss, and purify-css Compared

When building modern web applications, managing CSS efficiently is critical for performance, maintainability, and browser compatibility. The packages autoprefixer, cssnano, postcss, and purify-css each play a role in this ecosystem — but they serve very different purposes and often work together rather than compete directly. Let’s clarify what each does, how they fit into your build pipeline, and where you might run into pitfalls.

🧩 Core Roles: Processor vs Plugins vs Standalone Tools

postcss is not a CSS optimizer or prefixer by itself — it’s a tool for transforming CSS with JavaScript plugins. Think of it as the engine that powers many modern CSS workflows.

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

autoprefixer is a PostCSS plugin that automatically adds vendor prefixes (like -webkit-, -moz-) based on your target browsers.

// Input CSS
const input = 'display: grid;';

// After autoprefixer (with older browser targets)
// Output: display: -ms-grid; display: grid;

cssnano is also a PostCSS plugin that minifies and optimizes CSS by removing redundant code, shortening values, and applying safe transformations.

// Input
const input = '.foo { color: #ff0000; padding: 10px 10px 10px 10px; }';

// After cssnano
// Output: .foo{color:red;padding:10px}

purify-css, however, is a standalone tool (not a PostCSS plugin) that removes unused CSS selectors by analyzing your HTML and JavaScript files to see which classes are actually used.

// CSS
const css = '.used { color: red; } .unused { display: none; }';

// JS/HTML content
const content = ['<div class="used"></div>'];

// After purify-css
// Output: .used { color: red; }

⚠️ Important: As of 2023, purify-css is deprecated. Its npm page states: "This project is no longer maintained. Please use PurgeCSS instead." Do not use purify-css in new projects.

🔌 Integration Patterns: How They Work Together

In practice, postcss acts as the host, while autoprefixer and cssnano plug into it. A typical production build might look like this:

// Using PostCSS programmatically
const postcss = require('postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');

const result = await postcss([
  autoprefixer({ browsers: ['> 1%', 'last 2 versions'] }),
  cssnano({ preset: 'default' })
]).process(cssString, { from: undefined });

console.log(result.css); // Prefixed + minified CSS

You’d typically run this after your Sass/Less/CSS-in-JS compilation step and before bundling.

In contrast, purify-css (or its successor PurgeCSS) runs separately, usually as a final pass to strip unused rules:

// ❌ Do not use purify-css in new code
// Instead, use PurgeCSS with PostCSS via postcss-purgecss
const purgecss = require('@fullhuman/postcss-purgecss');

module.exports = {
  plugins: [
    purgecss({
      content: ['./src/**/*.html', './src/**/*.js']
    }),
    autoprefixer(),
    cssnano()
  ]
};

Note: Order matters in PostCSS. You generally want to remove unused CSS before minifying, so PurgeCSS (or similar) should come before cssnano.

🎯 When to Use What: Real Build Scenarios

Scenario 1: You Need Cross-Browser Compatibility

You’re supporting older browsers and writing modern CSS (e.g., gap, aspect-ratio).

  • Use autoprefixer (as a PostCSS plugin).
  • It reads your browserslist config and adds only the necessary prefixes.
// package.json
"browserslist": ["> 1%", "last 2 versions"]

Without this, your layout might break in Safari 14 or IE11 (if targeted).

Scenario 2: You Want Smaller CSS Files

Your production bundle includes verbose, unoptimized CSS.

  • Use cssnano (as a PostCSS plugin).
  • It safely compresses your CSS without changing behavior.
// Enables aggressive but safe optimizations
const result = await postcss([cssnano({ preset: 'advanced' })]).process(css);

Avoid running cssnano in development — it slows down rebuilds and makes debugging harder.

Scenario 3: Your App Has a Lot of Unused UI Library CSS

You’re using Bootstrap or Tailwind and shipping 500KB of CSS but only using 10%.

  • Use PurgeCSS (not purify-css) via @fullhuman/postcss-purgecss.
  • Analyzes your templates to keep only referenced classes.
// postcss.config.js
plugins: [
  require('@fullhuman/postcss-purgecss')({
    content: ['./src/**/*.{js,jsx,ts,tsx,html}'],
    defaultExtractor: content => content.match(/[^\s"'`;{}]+/g) || []
  })
]

Scenario 4: You’re Building a Custom CSS Toolchain

You need fine control over transforms (e.g., custom property fallbacks, RTL support).

  • Start with postcss and add plugins as needed.
  • The ecosystem has plugins for almost everything: postcss-custom-properties, postcss-rtl, etc.
const processor = postcss([
  require('postcss-custom-properties'),
  require('autoprefixer'),
  require('cssnano')
]);

⚠️ Common Misconceptions and Pitfalls

Myth: “cssnano removes unused CSS”

No. cssnano only optimizes used CSS (e.g., #ff0000red). It does not analyze your app to remove .btn-primary if you never use it. For that, you need tree-shaking tools like PurgeCSS.

Myth: “autoprefixer makes my CSS work everywhere”

It only handles prefixing, not feature polyfills. If you use grid and target IE10, you still need a polyfill — autoprefixer alone won’t help.

Pitfall: Running purify-css in 2024

As noted, purify-css is deprecated and unmaintained. It hasn’t kept up with modern JavaScript frameworks (React, Vue SFCs), leading to false positives/negatives. Migrate to PurgeCSS.

Pitfall: Wrong Plugin Order in PostCSS

If you minify before purging, cssnano might rename or restructure selectors in ways that confuse PurgeCSS. Always purge first, then minify.

// ✅ Correct order
plugins: [
  purgecssPlugin,
  autoprefixer,
  cssnano
]

📊 Summary: Responsibilities at a Glance

PackageTypePrimary JobWorks With PostCSS?
postcssCSS ProcessorRuns plugins to transform CSSN/A (it is the host)
autoprefixerPostCSS PluginAdds vendor prefixes✅ Yes
cssnanoPostCSS PluginMinifies and optimizes CSS✅ Yes
purify-cssStandalone ToolRemoves unused CSS (⚠️ deprecated)❌ No

💡 Final Recommendations

  • Always use postcss as your foundation if you need modern CSS processing.
  • Add autoprefixer if you support browsers that need prefixes (check caniuse.com).
  • Add cssnano in production builds to reduce file size.
  • Replace purify-css with PurgeCSS (via @fullhuman/postcss-purgecss) for dead code elimination.
  • Never use purify-css in new projects — it’s outdated and unsupported.

These tools are complementary, not competitors. Used together correctly, they form a robust pipeline for delivering lean, compatible, and maintainable CSS.

How to Choose: autoprefixer vs cssnano vs postcss vs purify-css

  • autoprefixer:

    Choose autoprefixer when you need to automatically add vendor prefixes to your CSS based on browser support requirements. It integrates seamlessly as a PostCSS plugin and uses your project's browserslist configuration to determine which prefixes are necessary. This is essential for ensuring consistent rendering across older browsers without manually maintaining prefix rules.

  • cssnano:

    Choose cssnano when you need to minify and optimize your CSS for production. It works as a PostCSS plugin and safely reduces file size by removing redundant code, shortening values, and applying other optimizations. Use it in your production build pipeline after other transformations like prefixing, but avoid using it during development as it hinders debugging.

  • postcss:

    Choose postcss as the foundation for any advanced CSS processing workflow. It doesn't do anything by itself but provides a plugin architecture that enables transformations like autoprefixing, minification, custom property handling, and more. If you need fine-grained control over your CSS pipeline or want to leverage modern CSS features with fallbacks, PostCSS is the standard choice in the JavaScript ecosystem.

  • purify-css:

    Do not choose purify-css for new projects — it is officially deprecated according to its npm page and repository. Instead, use PurgeCSS (typically via the @fullhuman/postcss-purgecss PostCSS plugin) to remove unused CSS selectors by analyzing your HTML and JavaScript files. PurgeCSS is actively maintained, supports modern frameworks, and integrates cleanly into PostCSS-based build processes.

README for autoprefixer

Autoprefixer Cult Of Martians

PostCSS plugin to parse CSS and add vendor prefixes to CSS rules using values from Can I Use. It is recommended by Google and used in Twitter and Alibaba.

Write your CSS rules without vendor prefixes (in fact, forget about them entirely):

::placeholder {
  color: gray;
}

.image {
  width: stretch;
}

Autoprefixer will use the data based on current browser popularity and property support to apply prefixes for you. You can try the interactive demo of Autoprefixer.

::-moz-placeholder {
  color: gray;
}
::placeholder {
  color: gray;
}

.image {
  width: -webkit-fill-available;
  width: -moz-available;
  width: stretch;
}

Twitter account for news and releases: @autoprefixer.

Sponsored by Evil Martians

Docs

Read full docs here.