tailwindlabs / tailwindcss

A utility-first CSS framework for rapid UI development.
https://tailwindcss.com/
MIT License
82.86k stars 4.2k forks source link

Invalid CSS generated for class like `[&>&]:before:XXX` #13877

Open moshest opened 4 months ago

moshest commented 4 months ago

What version of Tailwind CSS are you using?

For example: v3.4.4

Reproduction URL

https://play.tailwindcss.com/nQleJ1grpC

image

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.

adamwathan commented 4 months ago

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?

moshest commented 4 months ago

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.

adamwathan commented 4 months ago

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 👍