Autoprefixer Runs Without Errors but Adds No Prefixes: A Diagnostic Guide
PostCSS finishes cleanly but Autoprefixer adds nothing? Diagnose whether the config is ignored, the plugin isn't loaded, or Browserslist targets simply don't need prefixes.
15 Sept 2026, 22:33 UTC

Your PostCSS build finishes cleanly, the output file exists, and yet the CSS is byte-for-byte identical to the input — no -webkit-, no -ms-, nothing. This is one of the most common Autoprefixer failure modes, and the frustrating part is that it almost never throws an error. The plugin is either not loaded, not configured, or correctly deciding that no prefixes are needed. This guide walks through how to tell which situation you're in.
Recognizing the condition
The typical symptoms look like this:
- Output CSS lacks expected prefixes for flexbox, grid,
user-select, orappearance. - The build completes with exit code 0 and no warnings.
- Occasionally you see
Unknown plugin "autoprefixer"or aCannot find moduleerror instead — that's a different, easier problem (see the fixes below).
Cause and diagnostic table
| Symptom | Likely cause | First check |
|---|---|---|
| Output identical to input, no errors | Config file not being picked up at all | Confirm the config file location and format |
| Output identical to input, config looks right | Browserslist targets don't need prefixes | Run npx browserslist and inspect the target list |
Cannot find module 'autoprefixer' | Plugin not installed in the project | Check node_modules and package.json |
Unknown plugin warning | Plugin name misspelled or wrong config key | Compare config entry against the installed package name |
| Some prefixes appear, others don't | Working as intended — removed or unnecessary prefixes | Check the property against your Browserslist targets |
Ordered checks
1. Confirm the config is actually loaded
PostCSS looks for configuration in several places: postcss.config.js, a .postcssrc file (JSON or YAML), or a postcss key in package.json. If you have more than one of these — for example a stale postcss key in package.json left over from an older setup alongside a new postcss.config.js — the resolution order may pick the one you didn't intend, and it fails silently. Delete or consolidate duplicates.
A minimal working config looks like this (run from the project root, no special permissions needed):
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
};Note the plugin is invoked — require('autoprefixer') with parentheses, not just referenced. Passing the bare function without calling it is a classic mistake that some setups tolerate and others silently ignore.
2. Verify the plugin is installed and resolvable
From the project root:
npm ls autoprefixer postcssBoth packages should resolve to versions compatible with each other and with your Node.js version. Autoprefixer 10.x requires PostCSS 8.x; if you're on PostCSS 7 you need Autoprefixer 9.x. Running current Autoprefixer on a very old Node release can fail with syntax errors because the package uses newer JavaScript features.
3. Check what Browserslist is actually targeting
This is the most overlooked cause. Autoprefixer doesn't add every prefix that exists — it adds only the prefixes your Browserslist targets require. Browserslist is the shared configuration (in package.json or a .browserslistrc file) that declares which browsers you support. If your targets are all modern browsers, Autoprefixer correctly outputs nothing for flexbox or transitions, because nothing needs prefixing.
Run from the project root:
npx browserslistInspect the printed list. If you see only recent Chrome, Firefox, and Edge versions, missing -webkit- prefixes are expected behavior, not a bug. To force visible output for testing, temporarily set an aggressive query:
npx browserslist "ie 11"If that query resolves, set it in your config temporarily (overrideBrowserslist: ['ie 11'] in the Autoprefixer options) and rerun the build. Prefixes like -ms-flexbox should now appear, proving the pipeline works.
4. Isolate the pipeline with a trivial plugin
If prefixes are still missing, verify PostCSS itself is transforming anything at all. Temporarily add a plugin with obvious output, such as postcss-simple-vars, and use a variable in your source CSS. If the variable isn't substituted in the output, the problem is upstream — the build tool isn't invoking PostCSS on that file at all (common with misconfigured webpack postcss-loader rules or a wrong test regex for .css vs .scss).
5. Run PostCSS directly to bypass the bundler
From the project root, with the PostCSS CLI installed (npm i -D postcss-cli):
npx postcss src/styles.css -o dist/styles.css --verboseThe --verbose flag reports which plugins ran. If Autoprefixer appears here and prefixes show up in dist/styles.css but not in your bundler output, the fault is in the bundler integration, not PostCSS. Risk is minimal — this writes only to the output path you specify; use a scratch directory if you don't want to touch dist.
Fixes tied to findings
- Config not loaded: consolidate to a single
postcss.config.jsat the project root; remove thepostcsskey frompackage.json. - Plugin not called: change
require('autoprefixer')torequire('autoprefixer')()or use the string formplugins: ['autoprefixer']. - Version mismatch: align Autoprefixer 10 with PostCSS 8, or downgrade to Autoprefixer 9 for PostCSS 7.
- Targets too modern: adjust your Browserslist query to reflect the browsers you actually support — this is a product decision, not a build fix.
- Bundler not invoking PostCSS: check the loader chain order (e.g.,
postcss-loadermust run aftersass-loaderand beforecss-loaderin webpack).
When to escalate
Escalate to a minimal reproduction and a GitHub issue only after you've confirmed: the plugin loads with --verbose, Browserslist targets demonstrably require prefixes (e.g., ie 11), and a direct CLI run still produces no prefixes. At that point, capture your Node, PostCSS, and Autoprefixer versions plus the failing CSS snippet — genuinely broken prefixing with correct targets is rare and usually tied to a specific property or a very new CSS feature the plugin's data (from the caniuse-lite database) doesn't cover yet. Updating caniuse-lite (npx update-browserslist-db@latest) resolves a surprising number of these cases, since stale browser data is a quiet source of missing prefixes.
Verifying the fix
After any change, rebuild and grep the output for a prefix your targets require:
grep -c "\-webkit\-" dist/styles.cssA count above zero for targets that need it confirms the pipeline works. Keep in mind the inverse check too: if your targets are modern and the count is zero, that's the correct result — don't "fix" it by widening browser support you don't need.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.