postcss-loader

npm node deps tests coverage chat chat-postcss size

Loader to process CSS with postcss.

Getting Started

To begin, you'll need to install postcss-loader and postcss:

npm install --save-dev postcss-loader postcss

Then add the plugin to your webpack config. For example:

file.js

import css from 'file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-present-env',
                  {
                    // Options
                  },
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

Alternative use with config files:

postcss.config.js

module.exports = {
  plugins: [
    [
      'postcss-preset-env',
      {
        // Options
      },
    ],
  ],
};

The loader automatically searches for configuration files.

webpack.config.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

Name

Type

Default

Description

execute

{Boolean}

{Boolean} undefined Enable PostCSS Parser support in CSS-in-JS

Name

Type

Default

Description

postcssOptions

{Object\/Function}

{Object\/Function} defaults values for Postcss.process Set postcss options and plugins

Name

Type

Default

Description

sourceMap

{Boolean}

{Boolean} compiler.devtool Enables/Disables generation of source maps

execute

Type: Boolean Default: undefined

If you use JS styles the postcss-js parser, add the execute option.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.style.js$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                parser: 'postcss-js',
              },
              exec: true,
            },
          },
        ],
      },
    ],
  },
};

postcssOptions

Name Type Default Description

Name

Type

Default

Description

config

{Function\|Object\|Array<Function\|Object>}

{Function\|Object\|Array<Function\|Object>} [] Set PostCSS Plugins

Name

Type

Default

Description

plugins

{Function\|Object\|Array<Function\|Object>}

{Function\|Object\|Array<Function\|Object>} [] Set PostCSS Plugins

Name

Type

Default

Description

parser

{String\|Object\|Function}

{String\|Object\|Function} undefined Set custom PostCSS Parser

Name

Type

Default

Description

syntax

{String\|Object}

{String\|Object} undefined Set custom PostCSS Syntax

Name

Type

Default

Description

stringifier

{String\|Object\|Function}

{String\|Object\|Function} undefined Set custom PostCSS Stringifier

Type: Object|Function Default: undefined

Allows to set postcss options(http://api.postcss.org/global.html#processOptions) and plugins.

Object

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            parser: require('sugarss'),
          },
        },
      },
    ],
  },
};

Function

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: (loaderContext) => ({
            parser: require('sugarss'),
          }),
        },
      },
    ],
  },
};

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)
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).

webpack.config.js (recommended)

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          config: false,
        },
      },
    ],
  },
};

String

Allows to specify the absolute path to the config file.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          config: path.resolve(__dirname, 'custom.config.js'),
        },
      },
    ],
  },
};

Plugins

Type: Function|Object|Array<String|Function\|Object|Array> Default: []

It is recommended to specify plugins in the format Array<String\|Array> or Function that returns the same array as shown below. Object format ({pluginName: pluginOptions}) is deprecated and will be removed in the next major release.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          plugins: [
            'postcss-import',
            'postcss-nested',
            ['postcss-short', { prefix: 'x' }],
          ],
        },
      },
    ],
  },
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          plugins: (loader) => [
            ['postcss-import', { root: loader.resourcePath }],
            'postcss-nested',
            'cssnano',
          ],
        },
      },
    ],
  },
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            plugins: (loader) => [
              require('postcss-import')({ root: loader.resourcePath }),
              require('postcss-preset-env')(),
              require('cssnano')(),
            ],
          },
        },
      },
    ],
  },
};

⚠️ The method below for specifying plugins is deprecated.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          plugins: {
            'postcss-import': {},
            'postcss-nested': {},
            'postcss-short': { prefix: 'x' },
          },
        },
      },
    ],
  },
};

It is possible to disable the plugin specified in the config.

⚠️ The method below for specifying plugins is deprecated.

postcss.config.js

module.exports = {
  plugins: {
    'postcss-short': { prefix: 'x' },
    'postcss-import': {},
    'postcss-nested': {},
  },
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            plugins: {
              'postcss-import': {},
              'postcss-nested': {},
              // Turn off the plugin
              'postcss-short': false,
            },
          },
        },
      },
    ],
  },
};

Parser

Type: String|Object|Function Default: undefined

String

The passed string is converted to the form require('string').

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // Will be converted to `require('sugarss')`
            parser: 'sugarss',
          },
        },
      },
    ],
  },
};
Object

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            parser: require('sugarss'),
          },
        },
      },
    ],
  },
};
Function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            parser: require('sugarss').parse,
          },
        },
      },
    ],
  },
};

Syntax

Type: String|Object Default: undefined

String

The passed string is converted to the form require('string').

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // Will be converted to `require('sugarss')`
            syntax: 'sugarss',
          },
        },
      },
    ],
  },
};
Object

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            stringifier: require('sugarss'),
          },
        },
      },
    ],
  },
};

Stringifier

Type: String|Object|Function Default: undefined

String

The passed string is converted to the form require('string').

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // Will be converted to `require('sugarss')`
            stringifier: 'sugarss',
          },
        },
      },
    ],
  },
};
Object

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            stringifier: require('sugarss'),
          },
        },
      },
    ],
  },
};
Function

webpack.config.js

const Midas = require('midas');
const midas = new Midas();

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            stringifier: midas.stringifier,
          },
        },
      },
    ],
  },
};

sourceMap

Type: Boolean Default: depends on the compiler.devtool value

By default generation of source maps depends on the devtool option. All values enable source map generation except eval and false value.

webpack.config.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

module.exports = {
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'postcss-loader' },
          { loader: 'sass-loader' },
        ],
      },
    ],
  },
};

Examples

Autoprefixer

Add vendor prefixes to CSS rules using autoprefixer.

webpack.config.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 includes autoprefixer, so adding it separately is not necessary if you already use the preset. More information

PostCSS Preset Env

webpack.config.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.

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

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

If you want to process styles written in JavaScript, use the postcss-js parser.

webpack.config.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

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 to your configuration.
  2. You need to have only one default export per style module.

Extract CSS

Using mini-css-extract-plugin.

webpack.config.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 the postcss plugin to the webpack's output, 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

const customPlugin = () => (css, result) => {
  result.messages.push({
    type: 'asset',
    file: 'sprite.svg',
    content: '<svg>...</svg>',
  });
};

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

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

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()],
              },
            },
          },
        ],
      },
    ],
  },
};
  1. Pass loaderContext in plugin.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              config: 'path/to/postcss.config.js',
            },
          },
        ],
      },
    ],
  },
};

postcss.config.js

module.exports = (loaderContext) => ({
  postcssOptions: {
    plugins: [require('path/to/customPlugin')(loaderContext)],
  },
});

customPlugin.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

License

MIT