csstools / postcss-plugins

PostCSS Tools and Plugins
https://preset-env.cssdb.org/
MIT No Attribution
901 stars 71 forks source link

Add minimal-example reproduction for postcss-cascade-layers #375

Closed IanVS closed 2 years ago

IanVS commented 2 years ago

What would you want to propose?

I'm trying to create a reproduction for a possible issue I've encountered with postcss-cascade-layers, and tried to use npx @csstools/csstools-cli postcss-cascade-layers minimal-example.css, but got an error that the plugin is not available.

Suggested solution

I'm not sure how these are structured yet, but I assume it's a matter of adding the minimal example for this plugin the same as the others.

Additional context

No response

Validations

Would you like to open a PR for this feature?

romainmenke commented 2 years ago

Hi @IanVS,

@csstools/csstools-cli postcss-cascade-layers was only released yesterday and we usually wait a bit before adding it to other parts like the cli. We will try to do this next week.

What is really helpful for us when debugging is a minimal example with an indication of what you expected and what actually happened.

So feel free to just drop an example here.

IanVS commented 2 years ago

No worries, just opened this as a way to help track it, if nothing else. :) I'm putting together a small repo that I'll share in a different issue, once I figure out what's actually going on.

IanVS commented 2 years ago

While I have you, is there anything you can mention about how this plugin works, and any possible differences from how the browser works natively? For instance, it seems to look for matching selectors within different layers, modifying the least-priority selectors to add a :not() modifier. Is that correct? If so, will this handle code-splitting, when a new style might be imported after the initial batch, which could introduce new layers? I'm guessing that the analysis happens before code-splitting, so it wouldn't be an issue. I'm just looking for any gotchas, but I'll continue trying it out in the meantime.

romainmenke commented 2 years ago

The plugin works by analysing your CSS and creating "layers" or "buckets" of specificity.

@layer A, B;

@layer C {
  .foo {
    color: red;
  } 
}

3 layers + unlayered styles -> 4 layers or buckets

/* [0, 1, 0] */
.foo {
  color: red;
}

@layer C {
  /* [1, 0, 0] */
  #foo {
    color: green;
  } 
}

@layer C {
  /* [2, 1, 0] */
  #bar ~ #foo > .baz {
    color: purple;
  } 
}

most specific selector [2, 1, 0] -> layer or bucket size is 2

Depending on the layer order each selector is adjusted in specificity with :not() by N * BUCKET_SIZE

So unlayered styles (which are the most specific) get a their specificity adjusted by 6 (3 * 2)

Layer A is the least specific and get's no adjustment (0 2) Layer B is more specific and get's a small adjustment (1 2) ...


This also exposes the biggest gotcha, the plugin needs to see all of your styles to correctly determine all the variables in play.

romainmenke commented 2 years ago

@IanVS We have shipped a new version of csstools-cli : https://github.com/csstools/postcss-plugins/blob/main/cli/csstools-cli/CHANGELOG.md#140-june-3-2022

This includes support for Cascade Layers.

Thank you for reporting this 🎉