GithubHelp home page GithubHelp logo

csstools / postcss-nesting Goto Github PK

View Code? Open in Web Editor NEW
452.0 12.0 26.0 257 KB

Nest style rules inside each other

Home Page: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting

License: Creative Commons Zero v1.0 Universal

JavaScript 45.61% CSS 54.39%

postcss-nesting's Introduction

⚠️ PostCSS Nesting was moved to @csstools/postcss-plugins. ⚠️
Read the announcement

PostCSS Nesting PostCSS

NPM Version CSS Standard Status Build Status Support Chat

PostCSS Nesting lets you nest style rules inside each other, following the CSS Nesting specification. If you want nested rules the same way Sass works you might want to use PostCSS Nested instead.

a, b {
  color: red;

  & c, & d {
    color: white;
  }
}

/* becomes */

a, b {
  color: red;
}

a c, a d, b c, b d {
  color: white;
}

Usage

Add PostCSS Nesting to your project:

npm install postcss-nesting --save-dev

Use PostCSS Nesting to process your CSS:

import postcssNesting from 'postcss-nesting';

postcssNesting.process(YOUR_CSS /*, processOptions, pluginOptions */);

Or use it as a PostCSS plugin:

import postcss from 'postcss';
import postcssNesting from 'postcss-nesting';

postcss([
  postcssNesting(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);

PostCSS Nesting runs in all Node environments, with special instructions for:

Node Webpack Create React App Gulp Grunt

Deno

You can also use PostCSS Nesting on Deno:

import postcss from "https://deno.land/x/postcss/mod.js";
import postcssNesting from "https://cdn.jsdelivr.net/npm/postcss-nesting@10/mod.js";

await postcss([postcssNesting]).process(YOUR_CSS /*, processOptions */);

⚠️ Spec disclaimer

The CSS Nesting Module spec states on nesting that "Declarations occuring after a nested rule are invalid and ignored.". While we think it makes sense on browsers, enforcing this at the plugin level introduces several constrains that would interfere with PostCSS' plugin nature such as with @mixin

postcss-nesting's People

Contributors

ambar avatar antonio-laguna avatar csmosx avatar danielswensson avatar davidtheclark avatar jlhwung avatar johnalbin avatar jonathantneal avatar kurre avatar moox avatar philipbordallo avatar romainmenke avatar schelmo avatar tbremer avatar valtlai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

postcss-nesting's Issues

Nested BEM selectors not unwrapping

It appears that version 4.0 requires whitespace between the ampersand and nested selectors. This breaks a pattern that we have adopted for BEM style naming conventions, which had been working on the 3.0 releases.

It looks like the rule validation was the major change from 3 and 4. I was unable to decipher if this is valid based on the written spec.

Is this the expected results?

Input:

.box {
  & a { color: pink; }

  &__element {
    color: red;
  }

  &--modifier {
    color: yellow;

    & a {
      color: green;

      &:hover { text-decoration: underline; }
    }
  }
}

Output:

.box a {
    color: pink;
}
.box {
    &__element { color: red; }
    &--modifier { color: yellow; }
    &--modifier a { color: green; }
    &--modifier a:hover { text-decoration: underline; }
}

Can i nest a tag inside a class?

I'm asking because the docs don't include an example like this, which is influenced by my scss experience.

.icon-container {
    width: 202px;
    img {
        max-width: 80%;
    }
}

what I'm seeing is
image

postcss-import breaks ordering

This code:

primary.css

:root {
  --primary: {
    background: blue;
    color: white;

    &:hover {
      background: red;
    }

    &:active {
      background: pink;
    }
  };
}

Button.css

@import "./primary.css";

.__base {
  appearance: none;
  border: none;
  border-radius: 3px;

  &:hover {
    text-decoration: none;
  }

  &:focus {
    outline: none;
  }

  &::-moz-focus-inner {
    border: 0;
  }
}

.--primary {
  composes: __base;
  @apply --primary;
}

is compiled to:

.Button--primary:active{
      background: #008ecc
}.Button__base {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border: none;
  border-radius: 3px
}

.Button__base:hover{
      text-decoration: none
}

.Button__base:focus{
      outline: none
}

.Button__base::-moz-focus-inner{
      border: 0
}

.Button--primary {
    background: #008ecc;
    color: #fff;
}

.Button--primary:hover{
      background: #056aab
}

As you can see, .Button--primary:active should be at the bottom of document. Maybe postcss-import breaks ordering IMO.

Tools: webpack 2, css-loader, postcss-loader, latest [email protected]

Wrong nesting in media queries

postcss-nesting produces a wrong order of a media queries in the output.

It breaks things, a mobile image in the current example is replaced by tablet image.

Here's my CSS:

.section {
  &-new {
    position: relative;
    background-image: resolve('contents/whatinside/newbg.jpg');
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-size: 100% auto;

    @media (--retina) {
      background-image: resolve('contents/whatinside/[email protected]');
    }

    @media (--tablet-down) {
      background-image: resolve('contents/whatinside/newbg-tablet.jpg');

      @media (--retina) {
        background-image: resolve('contents/whatinside/[email protected]');
      }
    }

    @media (--mobileMax-down) {
      background-image: resolve('contents/whatinside/newbg-mobile.jpg');

      @media (--retina) {
        background-image: resolve('contents/whatinside/[email protected]');
      }
    }

    &:before {
      content: '';
      display: block;
      padding-top: 70%;

      @media (--tablet-down) {
        padding-top: 105%;
      }

      @media (--mobileMax-down) {
        padding-top: 402%;
      }
    }

    &-title {
      position: absolute;
      top: 8%;
      left: 0;
      right: 0;
      padding: 0 20px;
      font: 30px/1.4 $font-regular;
      text-transform: uppercase;
      text-align: center;
      color: #fff;

      @media (--tablet-down) {
        font-size: 24px;
      }

      @media (--mobileMax-down) {
        top: 5%;
      }
    }
  }

  margin-bottom: 40px;
  text-align: center;
  color: $color-f-main;
  background-image: resolve('contents/whatinside/palette-d.png');
  background-size: auto 100%;
  background-repeat: no-repeat;
  background-position: center right;
  background-color: $color-bg-light;

  @media (--desktop-down) {
    background-size: auto 100%;
    background-position: top 0px right -100px;
  }

  @media (--tabletMax-down) {
    background-image: resolve('contents/whatinside/palette-t.png');
    background-size: auto 120%;
    background-position: top right;
  }

  @media (--tablet-down) {
    background-size: auto 100%;
    background-position: top 0px right -50px;
  }

  @media (--mobileMax-down) {
    background-image: resolve('contents/whatinside/palette-m.png');
    background-size: 100% auto;
    background-position: center top;
  }
}

.palette {
  display: none;
}

Without the plugin I get this:

.section-new_1MT{
  position:relative;
  background-image:url('/assets/contents/whatinside/newbg.jpg');
  background-position:50% 50%;
  background-repeat:no-repeat;
  background-size:100% auto;
}

@media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/[email protected]');
  }
}

@media (max-width: 767px){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/newbg-tablet.jpg');
  }

  @media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi){
    .section-new_1MT{
      background-image:url('/assets/contents/whatinside/[email protected]');
    }
  }
}

@media (max-width: 543px){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/newbg-mobile.jpg');
  }

  @media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi){
    .section-new_1MT{
      background-image:url('/assets/contents/whatinside/[email protected]');
    }
  }
}

.section-new_1MT:before{
  content:'';
  display:block;
  padding-top:70%;
}

@media (max-width: 767px){
  .section-new_1MT:before{
    padding-top:105%;
  }
}

@media (max-width: 543px){
  .section-new_1MT:before{
    padding-top:402%;
  }
}

.section-new-title_2V3{
  position:absolute;
  top:8%;
  left:0;
  right:0;
  padding:0 20px;
  font:30px/1.4 'GothamProRegular','Helvetica, Arial, sans-serif';
  text-transform:uppercase;
  text-align:center;
  color:#fff;
}

@media (max-width: 767px){
  .section-new-title_2V3{
    font-size:24px;
  }
}

@media (max-width: 543px){
  .section-new-title_2V3{
    top:5%;
  }
}

@media (max-width: 1199px){
  .section_2-G{
    background-size:auto 100%;
    background-position:top 0px right -100px;
  }
}

@media (max-width: 991px){
  .section_2-G{
    background-image:url('/assets/contents/whatinside/palette-t.png');
    background-size:auto 120%;
    background-position:top right;
  }
}

@media (max-width: 767px){
  .section_2-G{
    background-size:auto 100%;
    background-position:top 0px right -50px;
  }
}

@media (max-width: 543px){
  .section_2-G{
    background-image:url('/assets/contents/whatinside/palette-m.png');
    background-size:100% auto;
    background-position:center top;
  }
}

.palette_3w2{
  display:none;
}
```css

When I switch on the plugin, I get this:

.section-new_1MT{
  position:relative;
  background-image:url('/assets/contents/whatinside/newbg.jpg');
  background-position:50% 50%;
  background-repeat:no-repeat;
  background-size:100% auto
}

@media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/[email protected]')
  }
}

@media (max-width: 767px){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/newbg-tablet.jpg')
  }
}

@media (max-width: 543px){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/newbg-mobile.jpg')
  }
}

.section-new_1MT:before{
  content:'';
  display:block;
  padding-top:70%
}

@media (max-width: 767px){
  .section-new_1MT:before{
    padding-top:105%
  }
}

@media (max-width: 543px){
  .section-new_1MT:before{
    padding-top:402%
  }
}

.section-new-title_2V3{
  position:absolute;
  top:8%;
  left:0;
  right:0;
  padding:0 20px;
  font:30px/1.4 'GothamProRegular','Helvetica, Arial, sans-serif';
  text-transform:uppercase;
  text-align:center;
  color:#fff
}

@media (max-width: 767px){
  .section-new-title_2V3{
    font-size:24px
  }
}

@media (max-width: 543px){
  .section-new-title_2V3{
    top:5%
  }
}

@media (max-width: 543px) and (-webkit-min-device-pixel-ratio: 1.25), (max-width: 543px) and (min-resolution: 120dpi){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/[email protected]')
  }
}

@media (max-width: 767px) and (-webkit-min-device-pixel-ratio: 1.25), (max-width: 767px) and (min-resolution: 120dpi){
  .section-new_1MT{
    background-image:url('/assets/contents/whatinside/[email protected]')
  }
}

@media (max-width: 1199px){
  .section_2-G{
    background-size:auto 100%;
    background-position:top 0px right -100px
  }
  }

@media (max-width: 991px){
  .section_2-G{
    background-image:url('/assets/contents/whatinside/palette-t.png');
    background-size:auto 120%;
    background-position:top right
  }
  }

@media (max-width: 767px){
  .section_2-G{
    background-size:auto 100%;
    background-position:top 0px right -50px
  }
  }

@media (max-width: 543px){
  .section_2-G{
    background-image:url('/assets/contents/whatinside/palette-m.png');
    background-size:100% auto;
    background-position:center top
  }
  }

.palette_3w2{
  display:none;
}
@media (max-width: 543px) and (-webkit-min-device-pixel-ratio: 1.25), (max-width: 543px) and (min-resolution: 120dpi)
@media (max-width: 767px) and (-webkit-min-device-pixel-ratio: 1.25), (max-width: 767px) and (min-resolution: 120dpi)

As you can see, max-width: 543px goes before max-width: 767px, so a mobile styles get overwritten by tablet styles. Order is not preserved.

[doc] @nest with several rules/selectors

From reading the doc I was expecting following to work

div {
  @nest .c1 &,
  @nest .c2 & {
    color: red;
  }
}

but the correct usage is

div {
  @nest
  .c1 &,
  .c2 & {
    color: red;
  }
}

A note or example about that would have saved me 30mn.

Thanks for postcss-nesting btw, I really like it.

Suggestion: throw error if used by unsupported PostCSS version

Hi there! Thanks for the fantastic library.

I recently ran into an issue whereby my nesting output was very messed up:

I believe the culprit ended up being the fact I was using postcss-nesting 2.3.0 within postcss 6, and postcss-nesting 2.3.0 does not have support for postcss 6. I fixed the issue by upgrading to postcss-nesting 3.0.0, which is the first version that does have support for postcss 6.

I wanted to suggest that we make postcss-nesting throw an error early if it is used by a version of postcss that it does not officially support, instead of the current behaviour which is to fail silently.

This took me awhile to debug and I'm keen to improve the experience for the next user who hits a similar problem.

What do you think? :-)

Cheers,
Oliver

Nesting media queries

It seems you can't nest media queries:

.main {
  @media (min-width: 100px) {
    color: blue;
    @media (min-device-pixel-ratio: 1.5) {
      color: red;
    }
  }
}

you get:

.main {
}

@media (min-width: 100px) {
    .main {
        color: blue;
    }

    @media (min-device-pixel-ratio: 1.5) {
        .main {
            color: red;
        }
    }
}

but I'd expect instead:

@media (min-width: 100px) and (min-device-pixel-ratio: 1.5) {
  .main {
    color: red;
  }
}

Nesting Rule Validation

Hello,

Regarding the commit for version 4.0.1, the nesting rule validation had an impact on the verification of selectors that start with -

Version 4.0.0

/^&([^A-z]|$)/.exec(selector)

Version 4.0.1

/&([^\w-]|$)/.exec(selector)

Considering this change, the first one ignored all letters, while the new one ignores all Word Character. However, the new regex also ignores the -.

As a consequence of the - being ignored, the postcss-nexting cannot be used with a CSS Loader containing the camelCase option dashes (for the mapping between the className and the selector). For example:

.list {
    list-style-type: none;

    &-item {
        display: flex;
        justify-content: space-between;
    }
}

Taking into consideration the example, the css classname list-item is ignored.

Therefore, is there any reason for ignoring the - character? If not, I would recommend changing the regex for the following one:

/&([^\w]|$)/.exec(selector)

Nesting issues 4.1.0

4.1.0 seems to solve most issues, but now something else doesn't work. Unsure if according with spec. It worked prior v3 though.

The following does not compile at all. Using postcss-selector-matches to unfold matches in the example; does not affect the postcss-nesting processing as & + & is expected to work.

li {
    color: cyan;

    /* Basic */
    & + & {
        color: tomato;
    }

    /* Complex */
    &:nth-last-child(n+2):matches(:first-child, :first-child ~ &) {
        color: red;
    }
}

Expected

li {
    color: cyan;
}

li + li {
    color: tomato;
}

li:nth-last-child(n+2):first-child,
li:nth-last-child(n+2):first-child ~ li {
    color: red;
}

Trailing semicolon cause some plugin's translate failed

I use postcss-nesting => px2rem. This px2rem plugin use semicolon to determine how to translate px unit.

For example

Source

.app {
  height: 100px; /*no*/
  & .hello {
    height: 100px; /*no*/
    height: 'PX2REM NO BUG';
  }
}

After postcss-nesting

.app {
  height: 100px /*no*/
}

.app .hello {
  height: 100px;

  /*no*/
  height: 'PX2REM NO BUG'; }

Than px2rem cannot resolve height: 100px /*no*/( semicolon missing ). After px2rem

.app {
  height: 1.333333rem;  /* incorrect */
}

.app .hello {
  height: 100px;
  height: 'PX2REM NO BUG';
}

https://github.com/songsiqi/px2rem

Do you have some ideal for resolve this problem?

Thank You! 39

TypeError: parent.before is not a function

When I go to build with postcss-nesting in my postcss.config.js

I get an error of:

TypeError: parent.before is not a function
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)

with my package.json containing:

"postcss": "7.0.3", "postcss-color-function": "^4.0.1", "postcss-custom-media": "7.0.4", "postcss-custom-properties": "^8.0.6", "postcss-flexbugs-fixes": "^4.1.0", "postcss-loader": "^3.0.0", "postcss-mixins": "^6.2.0", "postcss-nesting": "^7.0.0", "postcss-sorting": "^4.0.0",

when I take out postcss-nesting it builds fine.

Latest release confusion

@jonathantneal
Could you clarify what the latest release is?

npm says 4.0.1 but npm i postcss-nesting installs 2.3.1, which is the latest release here on github. Was there a rollback at some point?

Judging from the issue #35, it's not entirely ready for production as it breaks certain use cases.

Nesting depth

I recently pulled an update of this package (via cssnext) and noticed that I can no longer nest anything more than one level deep. I can't see anything in the specification for what's the maximum depth so thought I'd check that it wasn't a bug.

Cannot read property 'insertAfter' of undefined

I even don't know what causes this.

TypeError: Cannot read property 'insertAfter' of undefined
    at Rule.after (/path/to/project/node_modules/postcss/lib/node.js:411:21)
    at module.exports (/path/to/project/node_modules/postcss-nesting/lib/transform-nesting-rule.js:18:29)
    at module.exports (/path/to/project/node_modules/postcss-nesting/lib/transform.js:16:3)
    at /path/to/project/node_modules/postcss/lib/container.js:144:26
    at AtRule.each (/path/to/project/node_modules/postcss/lib/container.js:110:22)
    at AtRule.walk (/path/to/project/node_modules/postcss/lib/container.js:143:21)
    at /path/to/project/node_modules/postcss/lib/container.js:146:32
    at Rule.each (/path/to/project/node_modules/postcss/lib/container.js:110:22)
    at Rule.walk (/path/to/project/node_modules/postcss/lib/container.js:143:21)
    at /path/to/project/node_modules/postcss/lib/container.js:146:32
error Command failed with exit code 1.

Question

Hi @jonathantneal, i can't figure out if this expresion & + & works with this plugin. Take this example:

  .NagivationItem {
    color: var(--foregroundColor, #000);
    text-decoration: none;

    /* & + .Class works as expected but not this ...
       It should be .NagivationItem + .NagivationItem {}, got:
        .NagivationItem { & + & {..} }   
    */
    & + & {
      margin-left: 90px; 
    }
  }

Could not find a declaration file

I'm trying to run postcss with webpack in a simple bare bone setup. I get the following message in my editor:

Could not find a declaration file for module 'postcss-nesting'. '/Users/verpixelt/study/development/webpack-demo/node_modules/postcss-nesting/index.cjs.js' implicitly has an 'any' type.
  Try `npm install @types/postcss-nesting` if it exists or add a new declaration (.d.ts) file containing `declare module 'postcss-nesting';`ts(7016)

Running webpack doesn't result in an error tho the plugin does not work. I've tried both referencing the plugin inside the webpack.config.js and in a dedicated postcss.config.js with the same result.

Any idea what's going on here?

I've put everything in a repo: https://github.com/verpixelt/webpack-demo

Nested @media queries not in spec

According to the docs, this supports using @media rules as a nested selector:

a, b {

    @media (min-width: 30em) {
        color: yellow;
    }
}

However, I don’t see this anywhere in the editor’s draft. I’m not sure if this was pulled from the spec or just added here as a bonus, but this should probably be called out in the documentation (or removed entirely if the intent is to follow the spec as closely as possible).

Multiple @nest in combined selector don't transform

Input:

.a {
    display: flex;

    @nest .foo &,
    @nest .bar & {
        color: #fff;
    }
}

Output:

.a {
    display: flex;
}

.foo .a,
@nest .bar .a {
    color: #fff;
}

Expected:

.a {
    display: flex;
}

.foo .a,
.bar .a {
    color: #fff;
}

The second @nest is not transformed. This issue is different than #40 because the @nest selectors are combined with a comma.

Versions:

  • postcss: 7.0.6
  • postcss-nesting: 7.0.0

An empty rule is created if If there's no property before a nested rule

Hi,

If a root rules doesn't contain any property before the nest rule, it create an empty rule. Just wanted to know why ?

input.css

a {
    &:hover {
        color: purple;
    }
}

actual.css

a {
}

a:hover {
    color: purple
}

expected.css

a:hover {
    color: purple
}

if I refer to exemple 1 and exemple 2 in the specs, the following code

table.colortable {
  & td {
    text-align:center;
    &.c { text-transform:uppercase }
    &:first-child, &:first-child + td { border:1px solid black }
  }
  & th {
    text-align:center;
    background:black;
    color:white;
  }
}

should become

table.colortable td {
  text-align:center;
}
table.colortable td.c {
  text-transform:uppercase;
}
table.colortable td:first-child, table.colortable td:first-child+td {
  border:1px solid black;
}
table.colortable th {
  text-align:center;
  background:black;
  color:white;
}

but in fact, it add table.colortable {} empty rule

table.colortable {
}

table.colortable td {
    text-align: center;
}

table.colortable td.c {
    text-transform: uppercase;
}

table.colortable td:first-child, table.colortable td:first-child + td {
    border: 1px solid black;
}

table.colortable th {
    text-align: center;
    background: black;
    color: white;
}

by the way, thanks for all the great things you do for the community ... 👏

trailing semicolon missing for the last rule of root element

The input styles.css

:local(.styles) {
  width: 500px;
  height: 300px;
  background-image: url(images/login-background.jpg);
  background-size: cover;
  background-color: blue;
  & > .aa {
    background-color: red;
  }
}

the output

.styles_styles_xOQ {
  width: 500px;
  height: 300px;
  background-image: url(http://localhost:3000/dist/4cacff6a01b1d1e4aedda554d4711417.jpg);
  background-size: cover;
  background-color: blue
}
.styles_styles_xOQ > .aa{
  background-color: red;
}

As a result, the browser failed to recognize the rules for the first selector.

nested rules miss final semicolon

after this plugins' transformation

.a {
  &.b {
    display: block;
    color: #111;
  }
}

becomes

.a.b {
  display: block;
  color: #111
}

the last semicolon gets lost.

Why no Sass-style nesting?

In the Sass world, nesting works like this:

.parent {
    .child {
        font-size: 12px;
    }
}

which compiles to:

.parent .child { font-size: 12px; }

Why doesn't postcss-nesting support this? Or the better question is why doesn't the CSS nesting spec support this style of writing nested selectors? And yes, I've read the spec and its explanation for this being that its because it would create an unbounded lookahead, but I still wonder why there can't be a PostCSS plugin that implements this style of nesting?

The specific use case where this type of nesting is useful is for example when you import a global vendor stylesheet, such as bootstrap or icomoon and you want to nest those "global" styles inside of your app component's class name so that it "namespaces" the global vendor styles and scopes them to the specific component you need those styles for.

With postcss-nesting this isn't possible unless the vendor stylesheet is modified to add & in front of every single class name, which defeats the purpose of installing that vendor stylesheet and using as-is.

Nested query media was promoted

Hi, i use postcss-cssnext nesting feature to nesting the media query, but the result css media query was promoted.

there is the code

.left_column {
  position: fixed;
  width: 250px;
  height: 100%;
  background: #00ccff;
  color: var(--mainColor);

  & header {
    padding-top: 60px;
  }

  @media screen and (max-width: 1024px) {
    width: 210px;
  }
}

result

@media screen and (max-width: 1024px) {
  .left_column {
    width: 210px;
  }
}
.left_column {
   position: fixed;
   width: 250px;
   height: 100%;
   background: #00ccff;
   color: white
}

the media query before .left_column, make the media query be overwritten

when i remove & header {} ,the result is my expected

.left_column {
   position: fixed;
   width: 250px;
   height: 100%;
   background: #00ccff;
   color: white
}

@media screen and (max-width: 1024px) {
  width: 210px;
}

is there anything wrong? thanks

my code environment is
image

Composes

With nesting we can't use composes, right?

Incorrect indentation

Input:

.button {
  & i {
    color: black;
  }
}

Expected output: (2 spaces)

.button i {
  color: black
}

Actual output: (4 spaces)

.button i {
    color: black
}

Support for CSS @apply Rule

I can not use postcss-apply and postcss-custom-properties. This features are implemented in Polymer using JS. I get error

:root {
  /* Primary colors */
  --dark-primary-color:         var(--paper-indigo-700);
  --default-primary-color:      var(--paper-indigo-500);
  --light-primary-color:        var(--paper-indigo-100);
  --text-primary-color:         #fff; /* text / icons */

  /* Accent colors */
  --accent-color:               var(--paper-pink-a200);
  --text-accent-color:          #fff; /* text / icons */

  /* Background colors */
  --primary-background-color:   var(--paper-grey-50);
  --secondary-background-color: #fff;

  /* Text colors */
  --primary-text-color:         var(--paper-grey-900);
  --secondary-text-color:       var(--paper-grey-600);
  --disabled-text-color:        var(--paper-grey-400);

  /* Other colors */
  --divider-color:              var(--paper-grey-300);
}

.Main {
  background: var(--primary-background-color);

  @nest &-content {
    color: var(--primary-text-color);
    @media (max-width: 599px) {
      @apply(--paper-font-body);
    }
    @media (min-width: 600px) {
      @apply(--paper-font-body2);
      padding: 48px 62px;
    }
  }
}

->

Error: no writecb in Transform class

@nest Doesn't work in combination with postcss-modules-local-by-default

This plugin will untokenize the selector if used in combination with modules local by default. https://github.com/css-modules/postcss-modules-local-by-default

eg.

/* Source: */
.icon {
  @nest .is-active & { ... }
}

/* Desired Output: */
._3qOz7o9UPD9GOtDjAK .KhXtXYu-YdxXx5mi8K-RT { ... } /* .is-active .icon { ... }*/

/* Actual Output */
.isActive .KhXtXYu-YdxXx5mi8K-RT { ... } /* .is-active .icon { ... }*/

I'm not sure where to post this, since cssnext has to be applied after modules-local-by-default, I'm starting here 👍

Concatenative selectors

Hi @jonathantneal, thanks for making such a cool postcss plugin!

I feel like I've found a potential bug with this. The spec doesn't mention this behaviour specifically, but I'm quite sure it is undesired.

Input:

.foo {
  color: blue;
  &bar {
    color: red;
  }
}

This plugins output:

.foo {
  color: blue
}
.foobar {
  color: red;
}

I would expect to see an error, I think, as the spec suggests & is equivalent of :matches() - which, to my understanding, means they shouldn't concatenate like this.

Perhaps @tabatkins could clarify this?

Cannot nest more than one level deep.

Summary

When trying to nest more than one level deep, the plugin ignores nested selectors, and they appear nested in the output.

Example 1:

Given the following post-CSS:

input

.a {
  color: blue;
  {
    .b {
      color: blue;
      {
        .c {
          color: blue;
        }
      }
    }
  }
}

I'd expect to see the the following:

expected

.a {
  color: blue;
}
  .a .b {
    color: blue;
  }
    .a .b .c {
      color: blue;
    }

Instead I get:

actual

.a {
  color: blue
}
        .a .c {
          color: blue;
        }
    .a .b {
      color: blue;
      .a {
        .a .c {
          color: blue;
        }
      }
    }
      .a {
        .a .c {
          color: blue;
        }
      }

Example 2

This is from the spec (example #4):

input

  div, p {
    font-size: 10px;
    {.keyword {color: green;}}
    {.constant {
      color: red;
      background-color: green;
      {&:hover::after { content: " [" attr(value) "]";}}
    }}
  }

expected

  div, p {font-size: 10px;}
  div .keyword, p .keyword {color: green;}
  div .constant, p .constant {color: red; background-color: green;}
  div .constant:hover::after, p .constant:hover::after {content: " [" attr(value) "]";}

actual

div, p {
  font-size: 10px
}div:hover::after, p:hover::after { content: " [" attr(value) "]";}div .constant, p .constant {
    color: red;
    background-color: green;
    div , p {div:hover::after, p:hover::after { content: " [" attr(value) "]";}}
  }div .keyword, p .keyword {color: green;}
    div , p {div:hover::after, p:hover::after { content: " [" attr(value) "]";}}

Error after migrating to postcss-cssnext

I don't know how this is related but since I tried migrating from cssnext to postcss-cssnext I'm getting the following error from postcss-nesting when building with webpack:

ModuleBuildError: Module build failed: ModuleBuildError: Module build failed: TypeError: Cannot read property 'forEach' of undefined
    at transpileSelectors (/Users/me/myproject/node_modules/postcss-nesting/index.js:71:20)
    at /Users/me/myproject/node_modules/postcss-nesting/index.js:57:4

Here is my webpack config

postcss: function (webpack) {
    return [
      require('autoprefixer')({
        browsers: 'last 2 versions',
        remove: false // faster if not processing legacy css
      }),
      require('postcss-import')({
        path: path.join(__dirname, 'app'),
        addDependencyTo: webpack, // for HMR
        glob: true
      }),
      require('postcss-url')(),
      require('postcss-cssnext')(),
      require('postcss-mixins')(),
      require('postcss-nesting')(),
      require('postcss-browser-reporter')(),
      require('postcss-reporter')()
    ]
  },

And it is coming from this css file, which used to work fine before

@import 'variables/all';
@import 'mixins/verticalCenter';

:root {
  --button-height: 2.5em;
  --button-padding: 2em;
}

@define-mixin buttonCommon {
  white-space: nowrap;
  padding: 0;
  height: var(--button-height);
  text-transform: uppercase;
  color: var(--color-white);
  background-color: var(--color-gray);
  border: none;
  /*border-radius: var(--radius-circle);*/
  transition-property: color, background-color, border, transform;
  transition-duration: var(--transition-duration-s);
  -webkit-tap-highlight-color: transparent;
  -webkit-appearance: none;
  &:focus {
    outline: none;
  }

  &:disabled {
    background: var(--color-gray);
    color: var(--color-white);
  }

  width: 10em; /* todo find way to not stretch in flexbox */
}

.main {
  @mixin buttonCommon;
}

.content {
  @mixin verticalCenter;
  font-size: var(--font-size-l);
  /*font-weight: var(--font-weight-medium);*/
  margin-left: var(--button-padding);
  margin-right: var(--button-padding);
}

.isPrimary {
  background-color: var(--color-green);

  &:active {
    color: var(--color-gray);
  }
}

.isSecondary {
  background-color: var(--color-blue);

  &:active {
    color: var(--color-gray);
  }
}

Parsing error using + combinator

Hi Jonathan, i have the following issue using the @nest at-rule.

Using the > combinator inside a @nest selector it works fine. This snippet works as expected:

.Hint {
  color: blue

  @nest .Field:invalid > & {
    color: red;
  }
}

/*
	RETURNS
	.Hint {
	  color: blue
	}
	
	.Field:invalid > .Hint {
	    color: red;
	}
*/

But this returns a syntax error:

.Hint {
  color: blue

  @nest .Field:invalid + & {
    color: red;
  }
}

/*
	SHOULD RETURNS
	.Hint {
	  color: blue
	}
	
	.Field:invalid + .Hint {
	    color: red;
	}
*/

Module build failed: ParserError: Syntax Error at line: 1, column 16 at Generator.next ()

Now i know i could write the selector in another way to make it work, but i think it's just a sort of parsing bug because both are valid combinators, and i want to keep consistency using one syntax (using @nest).

nest class not work

module: {
   .....
   rules: [
      {
        test: /\.(css|postcss)$/,
        use: [
           {
                loader: 'css-loader',
                 options: {
                     minimize: true,
                 },
             },
             {
                 loader: 'postcss-loader',
                 options: {
                       plugins: function () {
                           return [
                                require('postcss-nesting')(),
                                require('postcss-import')({
                                    path: [
                                         './src'
                                     ]
                                 }),
                                 require('postcss-flex-fallback')(),
                                 require('postcss-px2rem')({
                                      remUnit: 75,
                                 }),
                                 require('autoprefixer')({ browsers: ['last 2 versions'] }),
                             ]
                       },
                },
           },
          { 
              loader: 'style-loader',
          }]
      },
     ...
    ]
  },

in a.postcss file

.main {
  background: #f1f2f4;
  padding: 10px;
  height: 90vh;
  width: 375px;
  margin: 0 5px;
  overflow-y: scroll;
  overflow-x: hidden;
  box-shadow: inset 0px 0px 5px 1px #ccc;

  & .nothingTip {
    height: 88vh;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 6rem;
    color: #EAE9E9;
  }
}

after compiling...

image

Does it support `& > .foo` ?

In the spec, this should be supported:

.foo {
  color: blue;
  & > .bar { color: red; }
}
/* equivalent to
   .foo { color: blue; }
   .foo > .bar { color: red; }
 */

But I tried this plugin, it's not supported.

Move to PostCSS org

I think you did great plugins that transform W3C compliant code and I think it would be nice to have them under the postcss org. Are you open to be added in this org & move some in there ?
poke @ai

Not all @nest at-rules are transformed

Version of postcss-nesting: 4.0.1

Input:

.a {
  color: black;
  @nest .a1 & {color: red;}
  @nest .a2 & {color: blue;}
  @nest .a3 & {color: green;}
  @nest .a4 & {color: yellow;}
}

.b {
  color: black;
  @nest .b1 & {color: red;}
  @nest .b2 & {color: blue;}
  @nest .b3 & {color: green;}
  @nest .b4 & {color: yellow;}
}

Output:

.a {
  color: black
}

.a1 .a {
  color: red
}

.a2 .a {
  color: blue
}

.a {

  @nest .a3 & {color: green;
  }

  @nest .a4 & {color: yellow;
  }
}

.b {
  color: black;
  @nest .b1 & {color: red;}
  @nest .b2 & {color: blue;}
  @nest .b3 & {color: green;}
  @nest .b4 & {color: yellow;}
}

Expected:

.a {
  color: black
}

.a1 .a {
  color: red
}

.a2 .a {
  color: blue
}

.a3 .a {
  color: green
}

.a4 .a {
  color: yellow
}

.b {
  color: black
}

.b1 .b {
  color: red
}

.b2 .b {
  color: blue
}

.b3 .b {
  color: green
}

.b4 .b {
  color: yellow
}

on v4.0.0 some nesting forms are not allowed anymore

On my stack I use BEM and I usually nest like this:

.header {
  position: relative;
  background: $color-primary;
  border-bottom: solid 1px rgba(255, 255, 255, 0.15);

  &__container {
    display: flex;
    align-items: center;
    min-height: calc($spacing-unit * 3);
    @mixin container;

    @media screen and (max-width: $width-md) {
      flex-wrap: wrap;
      padding: 0 $spacing-small;
    }
  }

But v4.0.0 it seems to break support of this form of nesting, and the Changelog says only this:
schermata 2017-05-22 alle 11 46 12

What I'm doing wrong?

{ Error: undefined:3:27389: missing '}'

.nav-trigger {
  .Site-header {
      .Navigation-menu {
        color:red;      
      }
  }
}
  reason: 'missing \'}\'',
  filename: undefined,
  line: 3,
  column: 27389,
  source: '~.Site-header .Navigation-menu{color:red}}' }

switched to postcss-nested fixed the problem

Please add support for apply rule

Could you add support for apply rule, check out this links?

.Navigation {
@nest &--menu {
    --paper-menu-selected-item: {
      color: var(--accent-color);
    };
  }
}

This plugin remove semicolon on end of custom property set... :-(

.Navigation--menu {
    --paper-menu-selected-item: {
      color: var(--accent-color);
    }
  }

------------^

Check out the PSK+
https://github.com/StartPolymer/polymer-starter-kit-plus

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.