Use cascade layers in CSS
npm install @csstools/postcss-cascade-layersnpm install @csstools/postcss-cascade-layers --save-dev
[PostCSS Cascade Layers] lets you use @layer following the [Cascade Layers Specification]. For more information on layers, checkout [A Complete Guide to CSS Cascade Layers] by Miriam Suzanne.
``css
target {
color: purple;
}
@layer {
target {
color: green;
}
}
/ becomes /
target:not(#\#) {
color: purple;
}
target {
color: green;
}
`
[PostCSS Cascade Layers] creates "layers" of specificity.
It applies extra specificity on all your styles based on :
- the most specific selector found
- the order in which layers are defined
`css
@layer A, B;
@layer B {
.a-less-specific-selector {
/ styles /
}
}
@layer A {
#something #very-specific {
/ styles /
}
}
@layer C {
.a-less-specific-selector {
/ styles /
}
}
`
most specific selector :
- #something #very-specific[2, 0, 0]
- 2 + 1
- -> 3 to ensure there is no overlap
the order in which layers are defined :
- AB
- C
-
| layer | previous adjustment | specificity adjustment | selector |
| ------ | ------ | ----------- | --- |
| A | 0 | 0 + 0 = 0 | N/A |B
| | 0 | 0 + 3 = 3 | :not(#\#):not(#\#):not(#\#) |C
| | 3 | 3 + 3 = 6 | :not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) |
This approach lets more important (later) layers always override less important (earlier) layers.
And layers have enough room internally so that each selector works and overrides as expected.
More layers with more specificity will cause longer :not(...) selectors to be generated.
> [!IMPORTANT]
> [PostCSS Cascade Layers] assumes to process your complete CSS bundle.
If your build tool processes files individually or processes files in parallel the output will be incorrect.
Using @csstools/postcss-bundler and @import statements is one way to make sure your CSS is bundled before it is processed by this plugin.
Add [PostCSS Cascade Layers] to your project:
`bash`
npm install postcss @csstools/postcss-cascade-layers --save-dev
Use it as a [PostCSS] plugin:
`js
const postcss = require('postcss');
const postcssCascadeLayers = require('@csstools/postcss-cascade-layers');
postcss([
postcssCascadeLayers(/ pluginOptions /)
]).process(YOUR_CSS /, processOptions /);
`
The onRevertLayerKeyword option enables warnings if revert-layer is used.revert-layer
Transforming for older browsers is not possible in this plugin.
Defaults to warn
`js`
postcssCascadeLayers({ onRevertLayerKeyword: 'warn' }) // 'warn' | false
`css`
/ [postcss-cascade-layers]: handling "revert-layer" is unsupported by this plugin and will cause style differences between browser versions. /
@layer {
.foo {
color: revert-layer;
}
}
The onConditionalRulesChangingLayerOrder option enables warnings if layers are declared in multiple different orders in conditional rules.
Transforming these layers correctly for older browsers is not possible in this plugin.
Defaults to warn
`js`
postcssCascadeLayers({ onConditionalRulesChangingLayerOrder: 'warn' }) // 'warn' | false
`css
/ [postcss-cascade-layers]: handling different layer orders in conditional rules is unsupported by this plugin and will cause style differences between browser versions. /
@media (min-width: 10px) {
@layer B {
.foo {
color: red;
}
}
}
@layer A {
.foo {
color: pink;
}
}
@layer B {
.foo {
color: red;
}
}
`
The @import at-rule can also be used with cascade layers, specifically to create a new layer like so: `css`
@import 'theme.css' layer(utilities);@import
If your CSS uses with layers, you will also need the [postcss-import] plugin. This plugin alone will not handle the @import at-rule.
This plugin will warn you when it detects that [postcss-import] did not transform@import at-rules.
`js``
postcssCascadeLayers({ onImportLayerRule: 'warn' }) // 'warn' | false
[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
[css-url]: https://cssdb.org/#cascade-layers
[discord]: https://discord.gg/bUadyRwkJS
[npm-url]: https://www.npmjs.com/package/@csstools/postcss-cascade-layers
[PostCSS]: https://github.com/postcss/postcss
[PostCSS Cascade Layers]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-cascade-layers
[Cascade Layers Specification]: https://www.w3.org/TR/css-cascade-5/#layering
[A Complete Guide to CSS Cascade Layers]: https://css-tricks.com/css-cascade-layers/
[Olu Niyi-Awosusi]: https://github.com/oluoluoxenfree
[Sana Javed]: https://github.com/sanajaved7
[Oddbird]: https://github.com/oddbird
[postcss-import]: https://github.com/postcss/postcss-import