PostCSS Logo
Sponsored by Evil Martians
[![npm][npm]][npm-url] [![node][node]][node-url] [![deps][deps]][deps-url] [![tests][tests]][tests-url] [![coverage][cover]][cover-url] [![size][size]][size-url] Webpack chat: [![chat][chat]][chat-url] PostCSS chat: [![chat-postcss][chat-postcss]][chat-postcss-url] # postcss-loader Loader to process CSS with [`PostCSS`](https://github.com/postcss/postcss). ## Getting Started To begin, you'll need to install `postcss-loader` and `postcss`: ```console npm install --save-dev postcss-loader postcss ``` Then add the plugin to your `webpack` config. For example: **file.js** ```js import css from 'file.css'; ``` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // Options }, ], ], }, }, }, ], }, ], }, }; ``` Alternative use with [config files](#config): **postcss.config.js** ```js module.exports = { plugins: [ [ 'postcss-preset-env', { // Options }, ], ], }; ``` The loader **automatically** searches for configuration files. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: ['style-loader', 'css-loader', 'postcss-loader'], }, ], }, }; ``` And run `webpack` via your preferred method. ## Options | Name | Type | Default | Description | | :---------------------------------: | :------------------: | :-----------------------------------: | :------------------------------------------- | | [`execute`](#execute) | `{Boolean}` | `undefined` | Enable PostCSS Parser support in `CSS-in-JS` | | [`postcssOptions`](#postcssOptions) | `{Object\/Function}` | `defaults values for Postcss.process` | Set `PostCSS` options and plugins | | [`sourceMap`](#sourcemap) | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps | ### `execute` Type: `Boolean` Default: `undefined` If you use JS styles the [`postcss-js`](https://github.com/postcss/postcss-js) parser, add the `execute` option. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.style.js$/, use: [ 'style-loader', { loader: 'css-loader', }, { loader: 'postcss-loader', options: { postcssOptions: { parser: 'postcss-js', }, execute: true, }, }, ], }, ], }, }; ``` ### `postcssOptions` Type: `Object|Function` Default: `undefined` Allows to set [`PostCSS options`](http://api.postcss.org/global.html#processOptions) and plugins. All `PostCSS` options are supported. There is the special `config` option for config files. How it works and how it can be configured is described below. We recommend do not specify `from`, `to` and `map` options, because this can lead to wrong path in source maps. If you need source maps please use the [`sourcemap`](#sourcemap) option. #### `Object` Setup `plugins`: **webpack.config.js** (**recommended**) ```js const myOtherPostcssPlugin = require('postcss-my-plugin'); module.exports = { module: { rules: [ { test: /\.sss$/i, loader: 'postcss-loader', options: { postcssOptions: { plugins: [ 'postcss-import', ['postcss-short', { prefix: 'x' }], require.resolve('my-postcss-plugin'), myOtherPostcssPlugin({ myOption: true }), // Deprecated and will be removed in the next major release { 'postcss-nested': { preserveEmpty: true } }, ], }, }, }, ], }, }; ``` **webpack.config.js** (**deprecated**, will be removed in the next major release) ```js module.exports = { module: { rules: [ { test: /\.sss$/i, loader: 'postcss-loader', options: { postcssOptions: { plugins: { 'postcss-import': {}, 'postcss-short': { prefix: 'x' }, }, }, }, }, ], }, }; ``` Setup `syntax`: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.sss$/i, loader: 'postcss-loader', options: { postcssOptions: { // Can be `String` syntax: 'sugarss', // Can be `Object` syntax: require('sugarss'), }, }, }, ], }, }; ``` Setup `parser`: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.sss$/i, loader: 'postcss-loader', options: { postcssOptions: { // Can be `String` parser: 'sugarss', // Can be `Object` parser: require('sugarss'), // Can be `Function` parser: require('sugarss').parse, }, }, }, ], }, }; ``` Setup `stringifier`: **webpack.config.js** ```js const Midas = require('midas'); const midas = new Midas(); module.exports = { module: { rules: [ { test: /\.sss$/i, loader: 'postcss-loader', options: { postcssOptions: { // Can be `String` stringifier: 'sugarss', // Can be `Object` stringifier: require('sugarss'), // Can be `Function` stringifier: midas.stringifier, }, }, }, ], }, }; ``` #### `Function` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.(css|sss)$/i, loader: 'postcss-loader', options: { postcssOptions: (loaderContext) => { if (/\.sss$/.test(loaderContext.resourcePath)) { return { parser: 'sugarss', plugins: [ ['postcss-short', { prefix: 'x' }], 'postcss-preset-env', ], }; } return { plugins: [ ['postcss-short', { prefix: 'x' }], 'postcss-preset-env', ], }; }, }, }, ], }, }; ``` #### `config` Type: `Boolean|String` Default: `undefined` Allows to set options using config files. Options specified in the config file are combined with options passed to the loader, the loader options overwrite options from config. ##### Config Files The loader will search up the directory tree for configuration in the following places: - a `postcss` property in `package.json` - a `.postcssrc` file in JSON or YAML format - a `.postcss.json`, `.postcss.yaml`, `.postcss.yml`, `.postcss.js`, or `.postcss.cjs` file - a `postcss.config.js` or `postcss.config.cjs` CommonJS module exporting an object (**recommended**) ##### Examples of Config Files Using `Object` notation: **postcss.config.js** (**recommend**) ```js module.exports = { // You can specify any options from http://api.postcss.org/global.html#processOptions here // parser: 'sugarss', plugins: [ // Plugins for PostCSS ['postcss-short', { prefix: 'x' }], 'postcss-preset-env', ], }; ``` Using `Function` notation: **postcss.config.js** (**recommend**) ```js module.exports = (api) => { // `api.file` - path to the file // `api.mode` - `mode` value of webpack, please read https://webpack.js.org/configuration/mode/ // `api.webpackLoaderContext` - loader context for complex use cases if (/\.sss$/.test(api.file)) { return { // You can specify any options from http://api.postcss.org/global.html#processOptions here parser: 'sugarss', plugins: [ // Plugins for PostCSS ['postcss-short', { prefix: 'x' }], 'postcss-preset-env', ], }; } return { // You can specify any options from http://api.postcss.org/global.html#processOptions here plugins: [ // Plugins for PostCSS ['postcss-short', { prefix: 'x' }], 'postcss-preset-env', ], }; }; ``` **postcss.config.js** (**deprecated**, will be removed in the next major release) ```js module.exports = { // You can specify any options from http://api.postcss.org/global.html#processOptions here // parser: 'sugarss', plugins: { // Plugins for PostCSS 'postcss-short': { prefix: 'x' }, 'postcss-preset-env': {}, }, }; ``` ##### Config Cascade You can use different `postcss.config.js` files in different directories. Config lookup starts from `path.dirname(file)` and walks the file tree upwards until a config file is found. ``` |– components | |– component | | |– index.js | | |– index.png | | |– style.css (1) | | |– postcss.config.js (1) | |– component | | |– index.js | | |– image.png | | |– style.css (2) | |– postcss.config.js (1 && 2 (recommended)) |– webpack.config.js | |– package.json ``` After setting up your `postcss.config.js`, add `postcss-loader` to your `webpack.config.js`. You can use it standalone or in conjunction with `css-loader` (recommended). Use it **before** `css-loader` and `style-loader`, but **after** other preprocessor loaders like e.g `sass|less|stylus-loader`, if you use any (since [webpack loaders evaluate right to left/bottom to top](https://webpack.js.org/concepts/loaders/#configuration)). **webpack.config.js** (**recommended**) ```js module.exports = { module: { rules: [ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, }, }, 'postcss-loader', ], }, ], }, }; ``` #### Boolean Enables/Disables autoloading config. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, loader: 'postcss-loader', options: { postcssOptions: { config: false, }, }, }, ], }, }; ``` #### String Allows to specify the path to the config file. **webpack.config.js** ```js const path = require('path'); module.exports = { module: { rules: [ { test: /\.css$/i, loader: 'postcss-loader', options: { postcssOptions: { config: path.resolve(__dirname, 'custom.config.js'), }, }, }, ], }, }; ``` ### `sourceMap` Type: `Boolean` Default: depends on the `compiler.devtool` value By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option. All values enable source map generation except `eval` and `false` value. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { sourceMap: true } }, { loader: 'postcss-loader', options: { sourceMap: true } }, { loader: 'sass-loader', options: { sourceMap: true } }, ], }, ], }, }; ``` Alternative setup: **webpack.config.js** ```js module.exports = { devtool: 'source-map', module: { rules: [ { test: /\.css$/i, use: [ { loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader' }, { loader: 'sass-loader' }, ], }, ], }, }; ``` ## Examples ### SugarSS You'll need to install `sugarss`: ```console npm install --save-dev sugarss ``` Using [`SugarSS`](https://github.com/postcss/sugarss) syntax. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.sss$/i, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1 }, }, { loader: 'postcss-loader', options: { postcssOptions: { parser: 'sugarss', }, }, }, ], }, ], }, }; ``` ### Autoprefixer You'll need to install `autoprefixer`: ```console npm install --save-dev autoprefixer ``` Add vendor prefixes to CSS rules using [`autoprefixer`](https://github.com/postcss/autoprefixer). **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1 }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'autoprefixer', { // Options }, ], ], }, }, }, ], }, ], }, }; ``` > :warning: [`postcss-preset-env`](https://github.com/csstools/postcss-preset-env) includes [`autoprefixer`](https://github.com/postcss/autoprefixer), so adding it separately is not necessary if you already use the preset. More [information](https://github.com/csstools/postcss-preset-env#autoprefixer) ### PostCSS Preset Env You'll need to install `postcss-preset-env`: ```console npm install --save-dev postcss-preset-env ``` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1 }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // Options }, ], ], }, }, }, ], }, ], }, }; ``` ### CSS Modules What is `CSS Modules`? Please [read](https://github.com/webpack-contrib/css-loader#modules). No additional options required on the `postcss-loader` side. To make them work properly, either add the `css-loader`’s `importLoaders` option. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, importLoaders: 1, }, }, 'postcss-loader', ], }, ], }, }; ``` ### CSS-in-JS and [`postcss-js`](https://github.com/postcss/postcss-js) You'll need to install `postcss-js`: ```console npm install --save-dev postcss-js ``` If you want to process styles written in JavaScript, use the [`postcss-js`](https://github.com/postcss/postcss-js) parser. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.style.js$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 2, }, }, { loader: 'postcss-loader', options: { postcssOptions: { parser: 'postcss-js', }, execute: true, }, }, 'babel-loader', ], }, ], }, }; ``` As result you will be able to write styles in the following way ```js import colors from './styles/colors'; export default { '.menu': { color: colors.main, height: 25, '&_link': { color: 'white', }, }, }; ``` > :warning: If you are using Babel you need to do the following in order for the setup to work > 1. Add [`babel-plugin-add-module-exports`](https://github.com/59naga/babel-plugin-add-module-exports) to your configuration. > 2. You need to have only one **default** export per style module. ### Extract CSS Using [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin). **webpack.config.js** ```js const isProductionMode = process.env.NODE_ENV === 'production'; const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { mode: isProductionMode ? 'production' : 'development', module: { rules: [ { test: /\.css$/, use: [ isProductionMode ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'postcss-loader', ], }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: isProductionMode ? '[name].[contenthash].css' : '[name].css', }), ], }; ``` ### Emit assets To write a asset from PostCSS plugin to the webpack, need to add a message in `result.messages`. The message should contain the following fields: - `type` = `asset` - Message type (require, should be equal `asset`) - `file` - file name (require) - `content` - file content (require) - `sourceMap` - sourceMap - `info` - asset info **webpack.config.js** ```js const customPlugin = () => (css, result) => { result.messages.push({ type: 'asset', file: 'sprite.svg', content: '...', }); }; const postcssPlugin = postcss.plugin('postcss-assets', customPlugin); module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [postcssPlugin()], }, }, }, ], }, ], }, }; ``` ### Add dependencies The dependencies are necessary for webpack to understand when it needs to run recompilation on the changed files. There are two way to add dependencies: 1. (Recommended). The plugin may emit messages in `result.messages`. The message should contain the following fields: - `type` = `dependency` - Message type (require, should be equal `dependency`) - `file` - absolute file path (require) **webpack.config.js** ```js const path = require('path'); const customPlugin = () => (css, result) => { result.messages.push({ type: 'dependency', file: path.resolve(__dirname, 'path', 'to', 'file'), }); }; const postcssPlugin = postcss.plugin('postcss-assets', customPlugin); module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [postcssPlugin()], }, }, }, ], }, ], }, }; ``` 2. Pass `loaderContext` in plugin. **webpack.config.js** ```js const path = require('path'); module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { config: path.resolve(__dirname, 'path/to/postcss.config.js'), }, }, }, ], }, ], }, }; ``` **postcss.config.js** ```js module.exports = (api) => ({ plugins: [ require('path/to/customPlugin')({ loaderContext: api.webpackLoaderContext, }), ], }); ``` **customPlugin.js** ```js const path = require('path'); const customPlugin = (loaderContext) => (css, result) => { loaderContext.webpack.addDependency( path.resolve(__dirname, 'path', 'to', 'file') ); }; module.exports = postcss.plugin('postcss-assets', customPlugin); ``` ## Contributing Please take a moment to read our contributing guidelines if you haven't yet done so. [CONTRIBUTING](./.github/CONTRIBUTING.md) ## License [MIT](./LICENSE) [npm]: https://img.shields.io/npm/v/postcss-loader.svg [npm-url]: https://npmjs.com/package/postcss-loader [node]: https://img.shields.io/node/v/postcss-loader.svg [node-url]: https://nodejs.org [deps]: https://david-dm.org/webpack-contrib/postcss-loader.svg [deps-url]: https://david-dm.org/webpack-contrib/postcss-loader [tests]: https://github.com/webpack-contrib/postcss-loader/workflows/postcss-loader/badge.svg [tests-url]: https://github.com/webpack-contrib/postcss-loader/actions [cover]: https://codecov.io/gh/webpack-contrib/postcss-loader/branch/master/graph/badge.svg [cover-url]: https://codecov.io/gh/webpack-contrib/postcss-loader [chat]: https://badges.gitter.im/webpack/webpack.svg [chat-url]: https://gitter.im/webpack/webpack [chat-postcss]: https://badges.gitter.im/postcss/postcss.svg [chat-postcss-url]: https://gitter.im/postcss/postcss [size]: https://packagephobia.now.sh/badge?p=postcss-loader [size-url]: https://packagephobia.now.sh/result?p=postcss-loader