Share variables between CSS and JS with Webpack + HMR

Usage no npm install needed!

<script type="module">
  import postcssVariablesLoader from '';



NPM Version License Github Issues Travis Status Coveralls

Allows you to share variables between CSS and JS with Webpack and HMR.

This loader transforms special CSS files to JS modules.
  • Shared variables between CSS and JS
  • HMR friendly, CSS changes are applied on the fly.

To be more JS friendly loader will:

  • strip px part from CSS px numbers
  • convert dashes-case to camelCase
  • check for runtime config mutations and access of missing keys (only in dev or es6 mode)


/* variables.config.css */

@custom-media --small-device (max-width: 480px))
:root {
  --primary-color: blue;
  --gutter: 30px;
/* component.css  */

@import 'colors.config.css'

.component {
  color: var(--primary-color);
  margin: 0 var(--gutter);

@media (--small-device) {
  /* styles for small viewport */

// component.js
import variables from 'colors.config.css';

  variables = {
    primaryColor: 'blue';
    gutter: 30;
    smallDevice: '(max-width: 480px)'
*/ = variables.primaryColor;

function add5ToGutter() {
  return 5 + variables.gutter;


yarn add --dev postcss-variables-loader
npm install --save-dev postcss-variables-loader

NB: You need to process CSS somehow (eg postcss) and imports inside css (eg via postcss-import)

Recommended webpack configuration: webpack.config.js with babel-loader

rules: [
    test: /\.config.css$/,
    loader: 'babel-loader!postcss-variables-loader'

  // dont forget to exclude *.config.css from other css loaders
    test: /\.css$/,
    exclude: /\.config.css$/,
    loader: 'css-loader!postcss-loader'


if production.env.NODE_ENV === 'development' it will try to wrap config inside Proxy in runtime. It is used to guard from accidental mutations or accessing missing keys. If you dont want this behaviour: pass es5=1:

loader: 'postcss-variables-loader?es5=1'