&__element (BEM-style nesting) compiles to invalid selector :is(.block)__element in v4.3.3
#20443
Replies: 5 comments 1 reply
|
Could you provide a git repo where it was working? In Lightning CSS playground (i.e. before 4.3), it compiles to: __element.block {
color: red;
}And in Vite with __element.block{color:red}Regardless, the nesting was always meant to follow native CSS behavior and not Sass-like behavior. |
|
@wongjn the same code was working with version 4.3.0, when I upgraded to the latest version (4.3.3), compiled CSS was broken (I haven't tried 4.3.1, 4.3.2). I'm using |
|
This is not postcss-nested, and the regression is narrower than the thread suggests. It landed in 4.3.3 specifically. I reproduced it with .block {
&__element { color: red; }
&:hover { color: blue; }
}/* tailwindcss 4.3.3 */
:is(.block)__element { color: red; }
.block:hover { color: blue; }Bisecting the same input across versions:
So through 4.3.2 Tailwind passed this nesting through untouched, which is why @ondrej-kaspar's setup worked: postcss-nested got it afterwards and expanded it Sass-style. Confirmed both ways with postcss-nested 8.0.1 in the pipeline: Plugin order does not change that, since the Tailwind plugin compiles the file itself rather than handing an AST along. postcss-nested on its own still resolves it correctly to On the Sass versus native question. @wongjn is right that this should follow native CSS, and native CSS does not concatenate: Worth noting the failure is silent. Through For anyone hitting this now, 4.3.2 is the last version that works with a postcss-nested setup, and writing Reproduced on Node 22, Linux x64, |
|
PostCSS doesn't run plugins in order because they are using a visitor-like API instead. If you were using a production build that triggered Lightning CSS, then .block {
&__element { color: red; }
}Would've been turned into: __element.block {
color: red;
}For normal builds, prior to Tailwind CSS 4.3.3, it was left untouched. As mentioned before, we did always "require" valid CSS, and If you want to keep using the postcss-nested plugin, you have to make sure that it's executed before Tailwind CSS sees it. You can try doing something like this in your postcss.config.js file: const postcss = require("postcss");
const postcssNested = require("postcss-nested");
module.exports = {
plugins: [
{
postcssPlugin: "postcss-nested-first",
Once(root, { result }) {
return postcss([postcssNested()]).process(root, {
from: result.opts.from,
});
},
},
require("@tailwindcss/postcss"),
],
};Let me know if this works for you |
|
Thanks @RobinMalfait, the visitor API point explains the thing I could not account for. I had tried postcss-nested on both sides of Tailwind and got Recording the version detail for anyone who lands here from a search, since it is the part that makes this look like a regression rather than a config problem: through 4.3.2 the nesting was passed through untouched, so a postcss-nested setup kept working by accident. 4.3.3 is the first version that resolves it, which is why the upgrade broke it. Agreed that |
Uh oh!
There was an error while loading. Please reload this page.
Since the native CSS nesting handling was introduced in v4.3.0 (#20124), the following input:
compiles to:
which is invalid CSS β :is() cannot be directly concatenated with an identifier like that.
Expected behavior
Since & is immediately followed by an identifier (no combinator or pseudo-class), it should be treated as a compound selector and produce:
This is how it worked before v4.3.0 when nesting was resolved by Lightning CSS, and how &:hover-style nesting (with a pseudo-class after &) still correctly resolves to :is(.block):hover.
Environment
Tailwind CSS v4.3.3
Reproduction
https://play.tailwindcss.com/nLeNDYZr4j?file=css
All reactions