-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: CSS Nesting implementation #9549
Conversation
🦋 Changeset detectedLatest commit: d470e13 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@AlbertMarashi is attempting to deploy a commit to the Svelte Team on Vercel. A member of the Team first needs to authorize it. |
…ve logic for encapsulation
Excluding CSS type element selectors closes sveltejs#9320 closes sveltejs#8587
closes sveltejs#8587
- parsing of at-rules - parsing of element type selectors
@dummdidumm @Rich-Harris @eltigerchino @gtm-nayan @benmccann I believe I have fully implemented support for the different kinds of CSS nesting, including a suite of tests for each kind of nesting. All tests on my end seem to be parsing fine Looking for feedback from a maintainer on my PR. |
Co-authored-by: Ben McCann <[email protected]>
Not sure how to handle unused selectors & etc with CSS nestign
@Rich-Harris I need you or someones help that knows the analyzer code in and out to help figure out if my approach is right, or if certain parts need to be re-done. I don't know if I'm checking for unused selectors properly Happy to implement, just need direction, but all my tests seem to be passing - just not sure if there's a better & less cryptic way to do this |
Bear with me for a little while longer — please hold off on making any additional commits, I need to sign off for the night but have some further changes in mind. Re your latest commit, the |
Unfortunately I'm starting to think we're barking up the wrong tree here. Flattening the selectors out like we're doing isn't quite correct. Consider a case like this: <x>
<y></y>
</x>
<style>
x y {
& & {
color: red;
}
}
</style> Internally, the <x>
<y></y>
</x>
<style>
x, y {
& & {
color: red;
}
}
</style> ...yields an internal representation of I think this is one of those cases where flattening seems like the easy and sensible thing to do, but what we actually need is a recursive approach. It turns out that the first case is equivalent to By doing this we also make the process much more efficient. Consider this case: <a>
<y></y>
</a>
<style>
a, b, c, d, e {
x {...}
}
</style> With the current approach — If instead we have a single Unfortunately I think this means a complete overhaul of this PR. It also means that we need to implement support for |
.x .y {
& & {
color: red;
}
} I'm fairly sure that is equivalent to because .x .y {
&& {
color: red;
}
} I believe is equivalent to The text will be red here in the browser (firefox) (but I think what we're doing though is potentially resulting in From my understanding, the spec doesn't really say how to handle this, but at least I think the browser handles it as From the spec/* Somewhat silly, but & can be used all on its own, as well. */
.foo {
color: blue;
& { padding: 2ch; }
}
/* equivalent to
.foo { color: blue; }
.foo { padding: 2ch; }
// or
.foo {
color: blue;
padding: 2ch;
}
*/
/* Again, silly, but can even be doubled up. */
.foo {
color: blue;
&& { padding: 2ch; }
}
/* equivalent to
.foo { color: blue; }
.foo.foo { padding: 2ch; }
*/ /* & can be used multiple times in a single selector */
.foo {
color: blue;
& .bar & .baz & .qux { color: red; }
}
/* equivalent to
.foo { color: blue; }
.foo .bar .foo .baz .foo .qux { color: red; }
*/
a, b {
& c { color: blue; }
} is equivalent to :is(a, b) c { color: blue; } |
|
Are you sure, I don't think that is how I programmed it. In the rule, the selectors are mapped, so we get one parent
But what actually happens I think right now is:
Which is wrong. I'm not sure what is actually occurring here, I need to test it out We need to do
|
Yes, I'm sure. Try this markup in CodePen or whatever: <x>
<y>
<y>this is red</y>
</y>
</x>
<style>
x y {
& & {
color: red;
}
}
</style> The text is red because the selector is equivalent to
|
Hmm. It seems you are correct here. From the spec .ancestor .el {
.other-ancestor & { color: red; }
}
/* equivalent to
.other-ancestor :is(.ancestor .el) { color: red; }
*/ Okay, so what do we need to do here in order to fix all of this? I've got some ideas
I feel like this should simplify the code to some degree in theory |
I'm working on it, starting with #10482. I'm going to close this PR as it will be very onerous to keep up with inbound changes, and the implementation is going to end up looking very different. As I say, bear with me! I appreciate you kicking this off — it's already forced some significant improvements in Svelte's CSS handling, with more to come. |
damn 😭 I wanted to become a contributor. I'd like to help if possible |
Right, that's what you'd expect |
You already helped! It's not visible as a PR author (yet!) but this PR sparked discussion and your back and forth with Rich will result in a better CSS parser in the end - thank you for that! |
Implementing the |
@Rich-Harris will do, I'll watch the other PR. |
Implement CSS nesting
Implements
&
prefix (ie.foo { & div { color: red } }
)&
type (element) selector (ie..foo { div { color: red } }
)&
for CSS Combinators (ie..foo { + div { color: red } }
)&
for class & ID selectors (ie..foo { .bar { color: red } }
)&
nesting selector to reverse rule context (ie..foo { .bar & { color: red } }
, equiv to.bar { .foo { color: red } }
)Closes:
ownSemicolon
flag in the PostCSS AST is set to true for rules with nodes. #9320