csstools / postcss-nesting

Nest style rules inside each other

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nesting depth

johngeorgewright opened this issue · comments

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.

I can't replicate this issue, do you have a css snippet I could try?

Edit: It looks like cssnext is still using version ^2.0.5 (>2 && <3) of this plugin maybe the maintainer, @MoOx, can chime in and see if there is an upgrade planned.

I'm seeing this too.

reduction:

.panel-editor {
  display: flex;
  & .edit-tools {
    width: 36px;
  }
  & .stage {
    border: 3px solid black;
    position: relative;
    & > canvas {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      width: 100%;
      height: 100%;
    }
  }
}

Warning in terminal:

    WARNING in ./~/css-loader?{"importLoaders":2}!./~/resolve-url-loader!./~/postcss-loader/lib!./stylesheets/main.css
    (Emitted value instead of an instance of Error)   resolve-url-loader cannot operate: CSS error
      /Users/kevin/repos/make-beliefs-comix/client/stylesheets/main.css:4:5: missing '}'
      at error (/Users/kevin/repos/make-beliefs-comix/client/node_modules/css/lib/parse/index.js:62:15)

package.json

{
  "name": "make-beliefs-comix",
  "private": true,
  "version": "0.0.1",
  "main": "client/main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack -p --colors --progress",
    "watch": "webpack --colors --progress --watch",
    "start": "npm run watch",
    "serve": "webpack-dev-server",
    "flow": "flow"
  },
  "dependencies": {
    "apollo-client": "^1.4.2",
    "babel-polyfill": "^6.23.0",
    "bcrypt": "^1.0.2",
    "comicneue": "github:captainn/comicneue",
    "dompurify": "^0.9.0",
    "graphql": "^0.10.1",
    "graphql-tools": "^1.0.0",
    "react": "^15.6.0",
    "react-dom": "^15.6.0",
    "react-motion": "^0.5.0",
    "react-redux": "^5.0.5",
    "react-router": "^4.1.1",
    "redux": "^3.6.0",
    "redux-thunk": "^2.2.0",
    "simpl-schema": "^0.3.0",
    "uniforms": "^1.18.2",
    "uniforms-unstyled": "^1.18.2"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.0.0",
    "babel-plugin-module-resolver": "^2.7.1",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-preset-env": "^1.5.2",
    "babel-preset-flow": "^6.23.0",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.4",
    "cssnano": "^3.10.0",
    "extract-text-webpack-plugin": "^2.1.2",
    "file-loader": "^0.11.2",
    "flow-bin": "^0.48.0",
    "postcss": "^6.0.2",
    "postcss-cli": "^4.1.0",
    "postcss-cssnext": "^2.11.0",
    "postcss-custom-properties": "^6.0.1",
    "postcss-loader": "^2.0.6",
    "resolve-url": "^0.2.1",
    "resolve-url-loader": "^2.0.2",
    "style-loader": "^0.18.2",
    "url-loader": "^0.5.9",
    "webpack": "^2.6.1",
    "webpack-dev-server": "^2.4.5"
  }
}

webpack.config.js

const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  entry: './scripts/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  devtool: 'generate-source-map',
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          { loader: 'babel-loader' }
        ],
        exclude: /node_modules/
      }, {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            { loader: 'css-loader', options: { importLoaders: 2 } },
            { loader: 'resolve-url-loader' },
            { loader: 'postcss-loader' },
          ]
        })
      }, {
        test: /\.(woff2|woff|eot|ttf|otf)$/,
        use: [ {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          }
        } ]
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('bundle.css'),
  ]
}

postcss.config.js

module.exports = {
  plugins: {
    'postcss-cssnext': {
      browsers: ['last 2 versions', '> 1%']
    },
    // 'cssnano': {}
  }
}

It's also hoisting all the nested rules to the top of the JS file - is that correct behavior?

In my testing, the regression comes from postcss-loader, not postcss-cssnext.
Try reverting postcss-loader to v.1.3.3, while keeping postcss-cssnext to v.2.11.0 and tell me if the issue disappears.

@johngeorgewright, which version of cssnext are you using? I’ve had to stop using that project because it’s often kept out of date.

I also met the same problem.
nest not work:
postcss-loader v2.0.6 and postcss-cssnext v2.11.0

nest work:
postcss-loader v1.3.3 and postcss-cssnext v2.11.0

@jonathantneal, I'm using postcss-cssnext ^2.11.0.

Hi,

I also have problems with the latest version of the plugin.
I installed the 3.0.0 version and runs correctly.

Looks like the postcss-nextcss plugin is pointing to a very old version of postcss-nesting.

https://github.com/MoOx/postcss-cssnext/blob/master/package.json#L49

Someone's attempted to update most dependencies:

MoOx/postcss-cssnext#374

I guess from here I should make the decision whether to just install all plugins manually or wait for the postcss-cssnext plugin to be updated.

Need to manualy install postcss-nesting and run it just before postcss-cssnext

Use dependencies they said it'll be fun they said

Same issue here, I dropped cssnext and am now just using postcss-nesting. Works great :)

I did the same. Dropped cssnext and added the cssnext modules individually (much of it, I skipped some of the more esoteric stuff) from this list: http://cssnext.io/features/

Now everything works as expected.

postcss.config.js:

module.exports = {
  plugins: {
    autoprefixer: {
      browsers: ['last 2 versions', '> 1%']
    },
    'postcss-custom-properties': {},
    'postcss-custom-media': {},
    'postcss-media-minmax': {},
    'postcss-custom-selectors': {},
    'postcss-nesting': {},
    'postcss-color-function': {},
    'postcss-color-hex-alpha': {},
    'postcss-font-variant': {},
    'postcss-font-family-system-ui': {}
  }
}

Okay, I had a talk with some brilliant type people about creating a new “next generation” css plugin based on granular spec statuses, like https://jonathantneal.github.io/css-db/

It still needs polish. For instance, it needs a “last updated” field for the spec status, and maybe a way to launch “What are the stages?” in a modal, just so people can easily track the status of this stuff. I’d also like to see some less exciting plugins like logical properties get included.

Anyway, if someone else is interested in working with me on this, I’d love even a hint of interest. I have no need to be the explicit owner or owner at all. I just want to endorse something realistic. I’m thinking it’s time to explicitly not endorse cssnext, which I have tried to help.

@jonathantneal Love this CSS DB project! The problem is that a solid reference requires esoteric CSS WG and browser implementation knowledge, not just looking at specs. For example, color expressions are listed as stage 2, whereas they're actually not going to happen until we figure out the syntax. What we know for sure is that the syntax will be different than what is currently in the spec, so anyone using color() or color-mod() syntax for "forwards compatibility" is up for a nasty surprise...

It may help to use something like Mavo so that people can send pull requests via a UI to update the data. I can help with that if you're interested.

100% interested. Likewise, let me know how I can help.

< barely-related-rant > I just want something honest. I mean, if I’m going to use some dreamy spec that’s likely to change, or if people are going to use @apply hell or high water (and I still see that syntax mentioned in css tricks articles), at least let folks do it with accessible knowledge. < /barely-related-rant >

100% interested. Likewise, let me know how I can help.

After poking around in the css-db repo a bit, the main issue I see is that the features are in separate json files instead of a single one. That would be a problem for Mavo, but also for third-party developers that want to do something useful with this data (programmatically), so if you want, you could work on that. :)

@jonathantneal @LeaVerou I don't know if work on the next cssnext is happening in css-db or anywhere else. I really want to help, as I am a cssnext user, I maintain (or try to maintain) neutrino-preset-postcss-cssnext and I want to see CSS 4+ succeed in every possible way. Can we centralize this discussion somewhere else?

I’m unsure where work will resume. Probably css-db. There are many other specs now available to us that are polyfilled via PostCSS, like image-set, :dir, and CSS Logical Properties. Those need to be added.

I’m closing this issue, as it tangents from the original issue, which was/is with cssnext.

@LeaVerou, I did not forget this conversation. Thank you for your feedback.

I finally got around this @ https://github.com/jonathantneal/css-db

One file. Features added. Published.

@jonathantneal Oh, awesome! I thought you had decided not to bother. Looks great!! I will take a look at enabling contributions via Mavo once I get some time. I’m just back after a 2 month absence and very swamped, do ping me if I don't get to it within a couple of weeks.

Hi, @LeaVerou! I’d love to learn more about how you think css-db could help Mavo or vice-versa. I also have no intention of pestering you, so do pardon the ping. Hope you’re well, too!

@jonathantneal This was our conversation on Jun 22 above:

Me:

It may help to use something like Mavo so that people can send pull requests via a UI to update the data. I can help with that if you're interested.

You:

100% interested. Likewise, let me know how I can help.

If you didn't understand what I was saying, how/why were you interested?

I haven't looked into Mavo. I will now. I was mostly pinging you because you'd expressed interest in some sort of contribution (or so I think) either to cssdb or from cssdb to something else).

Why would I express interest in your potential contribution to or usage of cssdb if I wasn't sure what you were saying? Because of your record. Like Tab and others, you make cool stuff, you know how to share ideas effectively, you care about web standards, and people listen to you. Why would I turn down a chance to collaborate?

I see. I suggested Mavo because it will make it easier for people to contribute to css-db. Instead of having to go through the pull request process, they can just click edit, make their changes, and click Save & "Suggest edits", all without ever leaving the website, and it will send a pull request behind the scenes.
The context was that this information changes extremely frequently, so we need to facilitate contributions.

Now I get the interface part of it, and I see how Mavo could enhance the frontend to reflect the source JSON and then allow changes back to it in focused visual interfaces (select, wysiwyg, etc). I’ll see if I can get that much integrated into a feature branch.

But how in the world that becomes a PR ... is a separate issue. I stumbled upon mavoweb/mavo#129 (comment) and, from a distance, that looks really difficult to accomplish right now. If you think that part is easy, that would be a welcome PR. Anyway, I’ve probably expired your time and this thread. Feel free to open something on https://github.com/jonathantneal/css-db/issues if your interest persists!

But how in the world that becomes a PR ... is a separate issue. I stumbled upon mavoweb/mavo#129 (comment) and, from a distance, that looks really difficult to accomplish right now.

Ahem, that issue is closed, because the functionality was actually implemented before Mavo was even launched :) Every time anyone uses a Github backend for their Mavo app's data, they automatically enable visual pull requests too.

Feel free to open something on jonathantneal/css-db/issues if your interest persists!

Will do, just no promises about when, it might be a few weeks. :) Or I could help you do it whenever, since that's much faster for me. :)

If I can bring this back to the original question: Are there limits on nesting depths?

I'm using postcss-nesting 2.3.1 as part of this stack and find the following behaviour:

.tags {
  margin: 0;
  padding: 0;

  & li {
    display: inline-block;
  }
}

Outputs as:

.tags {
  margin: 0;
  padding: 0
}

.tags li {
    display: inline-block;
}

While:

.project {

  & .tags {
    margin: 0;
    padding: 0;

    & li {
      display: inline-block;
    }
  }
}

Outputs as:

.project .tags {
    margin: 0;
    padding: 0;

    & li {
      display: inline-block;
    }
}

Edit
It seems that the limitation behaviour does not effect the first nested sibling, only subsequent ones, so would occur with something like:

.project {

  & .something-here {
  }

  & .tags {
    margin: 0;
    padding: 0;

    & li {
      display: inline-block;
    }
  }
}

I guess that suggests that this is a bug, not a feature. @jonathantneal should I create a new issue?

@smth Also running into this after a recent upgrade, but I'm not sure which upgrade exactly caused this. Did you get to the bottom of this?

When I was getting the above issue, I was unwittingly using an old version. I haven't come across it again as yet.

I managed to isolate the issue. I am using postcss 6.0.13 and postcss-nesting 2.3.0.

Given this script which compiles CSS that contains two levels of nesting:

const postcss = require('postcss');
const plugins = [require('postcss-nesting')()];

const css = `
.foo {
  color: 0;

  &:hover {
    color: 1;
  }

  &.bar {
    color: 2;

    &:hover {
      color: 3;
    }
  }
}
`;

postcss(plugins)
  .process(css)
  .then(r => console.log(r.css));

I get the following output:

.foo.bar {
    color: 2;

    &:hover {
      color: 3;
    }
}.foo {
  color: 0
}

.foo:hover {
    color: 1;
}

As you can see, it is only resolving nesting one level deep.

Upgrading postcss-nesting from 2.3.0 to 3.0.0 fixes the issue. I suspect the reason for this is postcss-nesting 3.0.0 contains support for postcss 6.0.0. (See changelog entry for postcss-nesting 3.0.0.) Of course you can upgrade to a newer version like postcss-nesting 6.0.0, although I'm too scared to do that in case the newer versions introduce new bugs!

Can I ask why this fails silently? Could we make postcss-nesting throw an error if it is used by a version of postcss which it does not support, which seems to be the problem we ran into here?

Also, in case this helps anyone else who lands on this issue, we were experiencing this problem (again using postcss 6.0.13 and postcss-nesting 2.3.0):

const postcss = require('postcss');
const plugins = [require('postcss-nesting')()];

const css = `
.link {
  &:visited {
    color: 0;
  }

  &:hover {
    color: 1;
  }
}
`;

postcss(plugins)
  .process(css)
  .then(r => console.log(r.css));

Outputs:

.link:hover {
    color: 1
}
.link {
}
.link:visited {
    color: 0
}

As you can see, the cascade order is incorrect. :visited should appear before :hover.

We fixed the issue in the same way as we fixed the nesting depth issue (above).