postcss / postcss-nested

PostCSS plugin to unwrap nested rules like how Sass does it.
MIT License
1.15k stars 66 forks source link

PostCSS Nested

<img align="right" width="135" height="95" title="Philosopher’s stone, logo of PostCSS" src="https://postcss.org/logo-leftp.svg">

PostCSS plugin to unwrap nested rules closer to Sass syntax.

.phone {
  &_title {
    width: 500px;
    @media (max-width: 500px) {
      width: auto;
    }
    body.is_dark & {
      color: white;
    }
  }
  img {
    display: block;
  }
}

.title {
  font-size: var(--font);

  @at-root html {
    --font: 16px;
  }
}

will be processed to:

.phone_title {
  width: 500px;
}
@media (max-width: 500px) {
  .phone_title {
    width: auto;
  }
}
body.is_dark .phone_title {
  color: white;
}
.phone img {
  display: block;
}

.title {
  font-size: var(--font);
}
html {
  --font: 16px;
}

Related plugins:

Alternatives:

<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">

Usage

Step 1: Install plugin:

npm install --save-dev postcss postcss-nested

Step 2: Check your project for existing PostCSS config: postcss.config.js in the project root, "postcss" section in package.json or postcss in bundle config.

If you do not use PostCSS, add it according to official docs and set this plugin in settings.

Step 3: Add the plugin to plugins list:

module.exports = {
  plugins: [
+   require('postcss-nested'),
    require('autoprefixer')
  ]
}

Options

bubble

By default, plugin will bubble only @media, @supports, @layer, @container, and @starting-style at-rules. Use this option to add your custom at-rules to this list.

postcss([require('postcss-nested')({ bubble: ['phone'] })])
/* input */
a {
  color: white;
  @phone {
    color: black;
  }
}
/* output */
a {
  color: white;
}
@phone {
  a {
    color: black;
  }
}

unwrap

By default, plugin will unwrap only @font-face, @keyframes and @document at-rules. You can add your custom at-rules to this list by unwrap option:

postcss([require('postcss-nested')({ unwrap: ['phone'] })])
/* input */
a {
  color: white;
  @phone {
    color: black;
  }
}
/* output */
a {
  color: white;
}
@phone {
  color: black;
}

preserveEmpty

By default, plugin will strip out any empty selector generated by intermediate nesting levels. You can set preserveEmpty to true to preserve them.

.a {
  .b {
    color: black;
  }
}

Will be compiled to:

.a {
}
.a .b {
  color: black;
}

This is especially useful if you want to export the empty classes with postcss-modules.

rootRuleName

The plugin supports the SCSS custom at-rule @at-root which breaks rule blocks out of their nested position. If you want, you can choose a new custom name for this rule in your code.

postcss([require('postcss-nested')({ rootRuleName: '_escape-nesting' })])
/* input */
.a {
  color: white;
  @_escape-nesting {
    .b {
      color: black;
    }
  }
}
/* output */
.a {
  color: white;
}
.b {
  color: black;
}