
What the config file does
A PostCSS config lists the plugins to run and, optionally, parser options such as a custom syntax or source maps. Runners such as Vite, postcss-loader and postcss-cli find it automatically using the postcss-load-config package, so you write it once and every tool shares it.
Supported file names
postcss-load-config (version 6.0.1 at the time of checking) searches your project for these files:
| Format | File names | Best for |
|---|---|---|
| JavaScript | postcss.config.js, .postcssrc.js | Most projects |
| ES module | postcss.config.mjs, .postcssrc.mjs | Projects using export default |
| CommonJS | postcss.config.cjs, .postcssrc.cjs | "type": "module" packages that still use require |
| TypeScript | postcss.config.ts, .mts, .cts | Typed projects |
| JSON / YAML | .postcssrc, .postcssrc.json, .postcssrc.yml | Simple, static plugin lists |
| package.json | a "postcss" key | Keeping config in one file |
The postcss-load-config README recommends adding an extension (such as .postcssrc.json) rather than using a bare .postcssrc.
A basic postcss.config.js
module.exports = {
plugins: [
require('postcss-nesting'),
require('autoprefixer')
]
}Plugins run in array order: nesting first, then Autoprefixer.
Object syntax with options
Many runners accept an object keyed by package name. The value is the plugin's options, or {} for none:
module.exports = {
plugins: {
'postcss-preset-env': { stage: 2 },
autoprefixer: {},
cssnano: { preset: 'default' }
}
}With the object form, setting a plugin to false disables it, which is handy for turning plugins off per environment.
ES module version
import autoprefixer from 'autoprefixer'
export default {
plugins: [autoprefixer]
}If your package.json contains "type": "module", a plain .js file is treated as ESM, so module.exports will fail. Rename it to .cjs or switch to export default.
JSON and package.json versions
{
"plugins": {
"autoprefixer": {}
}
}"postcss": {
"plugins": {
"autoprefixer": {}
}
}Different plugins for development and production
A JavaScript config can export a function. postcss-load-config passes a context object that includes env (from NODE_ENV) and, depending on the runner, file information:
module.exports = (ctx) => ({
map: ctx.env === 'development' ? { inline: false } : false,
plugins: {
'postcss-nesting': {},
autoprefixer: {},
cssnano: ctx.env === 'production' ? {} : false
}
})Now cssnano only runs in production builds and source maps only in development.
Other options you can set
parser,syntax,stringifier: use a custom syntax such aspostcss-scss.map: source map settings, for example{ inline: false }.fromandto: usually set by the runner, not by you.
Where to put the file
Place the config in your project root, next to package.json. postcss-load-config searches upward from the processed file's directory, so a config in the root covers the whole project. In a monorepo, each package can have its own.
Do not forget Browserslist
Autoprefixer and postcss-preset-env decide what to add based on your target browsers, which live in a separate Browserslist config:
defaults
not deadRun npx browserslist to print the resolved list.
Troubleshooting
“No PostCSS config found”
Check the file name and location. Runners such as postcss-cli need either a config file or plugins passed with --use.
“module is not defined in ES module scope”
You used module.exports in a file treated as ESM. Rename to postcss.config.cjs.
Plugin not found
The object form resolves plugin names from node_modules. Install the plugin as a dev dependency.
Tailwind v4 errors
Use @tailwindcss/postcss as the plugin key. See the PostCSS Tailwind guide.
Get PostCSS 8.5.32
Free, MIT licensed, downloaded from the official GitHub repository.


