tailwindcss
tailwindcss copied to clipboard
Invalid CSS generated for class like `[&>&]:before:XXX`
What version of Tailwind CSS are you using?
For example: v3.4.4
Reproduction URL
https://play.tailwindcss.com/nQleJ1grpC
Describe your issue
When using a class like [&>&]:before:content-[''] the generated CSS output contain invalid class with ::before::before instead of only one ::before:
+.\[\&\>\&\]\:before\:content-\[\'\'\]>.\[\&\>\&\]\:before\:content-\[\'\'\]::before::before {
-.\[\&\>\&\]\:before\:content-\[\'\'\]>.\[\&\>\&\]\:before\:content-\[\'\'\]::before {
--tw-content: '';
content: var(--tw-content);
}
The same apply for classes like [&+&]:before:XXX.
Hey thanks, we can definitely fix this (and it's already fixed in the v4 engine)!
I am curious though what the hell you are trying to do in a real project where you are using two & in an arbitrary variant 😆 Can you show me a real example of what you're doing?
Thanks!
I'm trying to style a tree-like shape where items can be one after another, or nested.
This specific style is very helpful to design the tree borders and handle the case of nesting and siblings without any code.
Got it! In your particular case, rearranging the variants to the correct order solves the problem:
https://play.tailwindcss.com/7ZU3MP4OnX
In v3, variants are applied inside out, so the variant on the right is applied first so you want before to be the first variant 👍
https://tailwindcss.com/docs/hover-focus-and-other-states#ordering-stacked-modifiers
For legacy reasons we have some special logic in place to try and hoist pseudo elements like ::before and ::after to the end of the selector even when you order your variants differently, but it's best to place them first and not rely on that band-aid hoisting logic, because as this issue demonstrates it's clearly not perfect 😄
To make thing's slightly worse this is the one significant breaking change we're planning for v4 because it surprises basically everyone, so in v4 variants will be applied from left-to-right which I think is a lot more intuitive. We'll provide a codemod for this though so it'll be an easy upgrade 👍
Just ran into (what I think is) the same issue with the class [&>p:first]:mt-0, which is generating the invalid selector .\[\&\>p\:first\]\:mt-0>p:first. I was able to make it work by changing it to [&>p:first-child]:mt-0.
Hey!
Going to close this issue now that Tailwind CSS v4 is out. In v4 the correct CSS should be generated because the order of variants is different (and more expected). E.g.: https://play.tailwindcss.com/LMHx5rBgiL
I would recommend to try and upgrade to Tailwind CSS v4. You can find the upgrade guide here: https://tailwindcss.com/docs/upgrade-guide
We also have a CLI tool that can help with upgrading your project(s): https://tailwindcss.com/docs/upgrade-guide#using-the-upgrade-tool
@ysulyma The :first pseudo-class is not a valid pseudo-class, but as you noticed you have to use :first-child instead. In Tailwind CSS we have a first variant that uses first-child behind the scenes.
If you want, you can use stacked variants to generate the CSS you want.
[&>p]:first:mt-0 or *:[p]:first:mt-0
These would generate the following CSS:
:is(.\*\:\[p\]\:first\:mt-0 > *):is(p):first-child {
margin-top: calc(var(--spacing) * 0);
}
:is(.\[\&\>p\]\:first\:mt-0 > p):first-child {
margin-top: calc(var(--spacing) * 0);
}
Hope this helps!