postcss-plugins
postcss-plugins copied to clipboard
custom selector and custom media do not play nice with cascade layers
I think this behaviour is largely undefined at the moment but declaring custom selectors and custom media inside @layer does not work.
Should it work?
wow, that's a big question. I'm not sure. On one hand it's like, nope, shouldn't work and the other hand is a big mayybeee?
mayybeee
Hehe, after typing this up I kept coming back to that :D
I think in theory they could work, but them being nested in @layer just doesn't have any effect.
It will be safest if we keep the current (broken) behaviour and wait until the relevant specs are updated.
Forgot to mention that I encountered this with imported styles where it is a bit more unexpected.
/* file-alpha.css */
@custom-media --small (min-width: 320px);
/* file-beta.css */
@import url(file-alpha.css) layer(media-queries);
I'm pretty sure we did spec this - but in a short mention nested between examples:
Name-defining at-rules such as
@keyframesor@font-facethat are defined inside cascade layers also use the layer order when resolving name collisions.
I think that would apply to any sort of custom-property/selector/media at-rules, which are generally name-defining. So that means they should:
- Work as expected even inside
@layer - If there are name conflicts, the higher layer should win (this can be achieved by ordering them, I think?)
Thank you @mirisuzanne for finding this issue and sharing this.
I've been working on an updated version which ensures this works as you describe : https://github.com/csstools/postcss-plugins/pull/543
The main issue was that the plugins that handle custom selectors and custom media transformed the CSS before the cascade layers plugin.
Resolving this will be part of the upcoming major release of postcss-preset-env, where we hope to align everything much more closely with the CSS specifications.
I got side-tracked a bit recently taking on maintenance for the polyfill-library and 9to5 work. Hopefully more time will be available soon!
@romainmenke Thanks for clarification. Could you give a small update when a fix / next major release could be available? I've to decide if we start using this on a quite big project and if its just about a couple of weeks I would take the risk :) Is this part of your v8 release cause I couldn't find a hint on your project board about that topic. Thanks for your help!
- we want to ship v8 with a version of nesting that will land in browsers, we don't want to ship v9 a short time after only because of nesting
- we want to have solved
@mediaparam parsing - we want to have an implementation of logical properties that is much simpler and more correct at the same time.
I am currently working on 1 and 2. I would not count on v8 being ready within the next few weeks :)
@romainmenke Thanks for you detailed answer! 🙏🏽
This is resolved in the latest pre-release version of postcss-preset-env : https://github.com/csstools/postcss-plugins/blob/postcss-preset-env--v8/plugin-packs/postcss-preset-env/CHANGELOG.md#800-alpha1-november-14-2022
I want this fix, but I also use postcss-env-function. That pre-release also says "Removed postcss-env-function (breaking)." So:
- Does this mean that if I want this fix via
postcss-preset-env, I need to abandonpostcss-env-function? - If so, should I be able to install
[email protected]atop my setup (that relies onpostcss-env-function) without breaking something?
@wesleyboar thanks for reaching out!
- Yes, and no.
- You'll get an error because of mismatched dependencies which you can choose to ignore but we won't be supporting such an environment so errors could happen.
Clarifying the answer to 1, you should be able to install postcss-env-function separately as it will stay frozen. We won't be releasing new fixes for that plugin nor relying on it for postcss-preset-env as part of the plugin pack. However, you still should be able to use it either as part of your stack of PostCSS plugins or even use insertBefore/insertAfter (see docs) with PostCSS Preset Env to inject it there.
My 2:20-morning brain could not think to install postcss-env-function separately. Thank you.
I tried installing the beta alpha and postcss-env-function. I do not see the fix succeed.
Has my 3:20-morning brain done anything wrong?
Source & Config
package.json (abbreviated)
"peerDependencies": {
"commander": "^9.4.1",
"cssnano": "^5.1.14",
"js-yaml": "^4.1.0",
"merge-lite": "^1.0.2",
"node-cmd": "^5.0.0",
"npm-watch": "^0.11.0",
"postcss": "^8.4.18",
"postcss-banner": "^4.0.1",
"postcss-cli": "^10.0.0",
"postcss-extend": "^1.0.5",
"postcss-env-function": "4.0.6",
"postcss-import": "^15.0.0",
"postcss-preset-env": "^8.0.0-alpha.1",
"postcss-replace": "^2.0.0"
},
"devDependencies": {
"@frctl/fractal": "^1.5.13",
"@frctl/mandelbrot": "^1.10.1"
},
No dependencies. Long story. Temporary. Does it matter?
npm list
➜ Core-Styles git:(dev--task/form-patterns--task/base-cms-portal-header) ✗ npm list postcss-env-function
@tacc/[email protected] /Users/wbomar/Code/Core-Styles
└── [email protected]
➜ Core-Styles git:(dev--task/form-patterns--task/base-cms-portal-header) ✗ npm list postcss-custom-selectors
@tacc/[email protected] /Users/wbomar/Code/Core-Styles
└─┬ [email protected]
└── [email protected]
src/.postcssrc.yml
plugins:
postcss-import:
path:
- src/lib
postcss-extend: {}
postcss-env-function:
importFrom:
- src/lib/_themes/default.json
postcss-preset-env:
stage: false
features:
custom-media-queries: true
media-query-ranges: true
custom-selectors: true
cssnano:
preset:
- default
- discardDuplicates:
exclude: true
mergeRules:
exclude: true
postcss-banner:
banner: '@tacc/core-styles v0.11.0-30-g66400cb+ | MIT | github.com/TACC/Core-Styles'
inline: true
important: true
postcss-replace:
pattern: ../../fonts/
data:
replaceAll: fonts/
src/.../c-button.css
@custom-selector :--disabled :disabled,[disabled];
.c-button {
display: inline-block;
box-sizing: border-box;
border-width: var(--global-border-width--normal);
border-style: solid;
}
.c-button:not(:--disabled) {
cursor: pointer; /* WARNING: Opinionated */
}
No @import
✓ The @custom-selector is parsed away.
dist/c-button.css
/*! @tacc/core-styles v0.11.0-30-g66400cb+ | MIT | github.com/TACC/Core-Styles */.c-button{border-style:solid;border-width:var(--global-border-width--normal);box-sizing:border-box;display:inline-block}.c-button:not(:is(:disabled,[disabled])){cursor:pointer}
Use @import
ⓧ The @custom-selector remains, unparsed.
src/.../core-styles.base.css
/*! core-styles.base.css */
@import url("./components/c-button.css") layer(components);
dist/core-styles.base.css
/*! @tacc/core-styles v0.11.0-30-g66400cb+ | MIT | github.com/TACC/Core-Styles */
/*! core-styles.base.css */@layer components{@custom-selector :--disabled :disabled,[disabled];.c-button{border-style:solid;border-width:var(--global-border-width--normal);box-sizing:border-box;display:inline-block}.c-button:not(:--disabled){cursor:pointer}}
@wesleyboar I don't see anything immediately wrong there but I'm not really familiar with layers @romainmenke can you chime in here?
I don't see env being used there though either but I don't think it has anything to do.
PS: Thanks a ton for testing the alpha! ❤️
I neglected the postcss-env-function in my "test case". It is active, but you're right, it has nothing to do.
I'll check whether postcss-env-function still works after I can use @layers+@import fix or find workaround.
——— Update ———
I neglected to enable the cascade-layers plugin.[^1] After enabling, alpha version, so far, seems to work for my use case.
[^1]: I have most features disabled, and enable any plugin I want to use, unless I forget, like I had today.
Investigating the issue reported by @wesleyboar I noticed that the current fix we implemented for the original issue doesn't work at all.
This didn't come up before because at the time of creating that fix it wasn't allowed to nest @layer.
By running cascade-layers before any other plugin we force that plugin to support everything. This includes things like nested css.
The cascade-layers plugin needs to be able to always understand the most modern syntax.
I suggest we rollback the latest changes and try something else :
cascade-layersis always last- all plugins for name defining at rules needs to have a basic understanding of Cascade Layers
We shift the burden from the cascade-layers plugin to a few other plugins.
Those plugins do not need to be capable of the entire Cascade Layers feature. Only just enough to know which declaration has priority if there are naming conflicts.
Hi everyone!
We have "embedded" support for cascade layers into these plugins. This removes all bugs and issues the might result from having multiple PostCSS plugins that need to work together.
Thank you for all the feedback and insights 🙇