Skip to content
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

Duplicated generated Svelte class .foo.svelte-r4nd0m.svelte-r4nd0m in CSS selector #9009

Closed
tholewebgods opened this issue Jul 20, 2023 · 3 comments

Comments

@tholewebgods
Copy link

Describe the bug

Svelte generates internal CSS classes and adds them to nodes and CSS selectors, as far as I can tell, for namespacing.

In some constellations, Svelte generates CSS selectors with the internal CSS selector added twice, i.e. for an element with class .foo Svelte compiles the CSS rule .foo.svelte-r4nd0m.svelte-r4nd0m.

  1. This behavior is unexpected.
  2. When removing adjacent selectors, the behavior disappears (in the MCVE removing the .state .foo selector changes the outcome)

See the marked selector:

svelte-generated-class-duplication-marks

Reproduction

https://svelte.dev/repl/01fd443e12b44915a8cb871fcf067257?version=4.0.5

<x-foo class="state" >
  <span class="foo">X</span>
  <span class="bar">X</span>
</x-foo>

<style>
	.state .foo {
	  background: #f00;
	}

	.bar {
	  border: 1px solid #f0f;
	}
</style>

The .bar element gets the .svelte-r4nd0m class twice.

Logs

No response

System Info

- Multiple Platforms (Webpack 5 + svelte-loader, CodeSandbox, svelte.dev REPL)
- Svelte 3.55.0, 4.0.5

Severity

annoyance

@geoffrich
Copy link
Member

Duplicate of #4374. You can find an explanation of why this occurs in this comment: #4374 (comment)

@geoffrich geoffrich closed this as not planned Won't fix, can't repro, duplicate, stale Jul 20, 2023
@tholewebgods
Copy link
Author

Wait, not so fast.

In the mentioned example "#1277" I can see that the selector to span needs to get heavier by adding a second class. But in my example the two selectors are independent to each other (class selector used, no element selector used).

To the argument in the linked issue:

[...] not any element outside the component.

How can the selector .foo.svelte-r4nd0m match anything outside the component, when .svelte-r4nd0m is specific to this component?

@geoffrich
Copy link
Member

But in my example the two selectors are independent to each other (class selector used, no element selector used).

Sure, but it's the same root issue as #4374.

How can the selector .foo.svelte-r4nd0m match anything outside the component, when .svelte-r4nd0m is specific to this component?

That part of the explanation is about why Svelte adds scoping classes to the first and last selector in a style rule. If you have a rule .foo .what .bar and Svelte only rewrote it to .foo.svelte .what .bar, then that style could apply to .bar elements outside of the component. So it needs to rewrite to .foo.svelte .what .bar.svelte instead. But doing that could change the relative specificity when compared to other style rule, so Svelte adds additional scoping classes to make sure every other style rule has its specificity increased by the same amount.

I explained this in more detail in a blog post a couple years back, if that helps you understand what's going on: https://geoffrich.net/posts/svelte-scoped-styles/#heading-specificity-and-scoping

But either way, discussion of what Svelte should do differently in this case should happen in #4374 to keep the conversation centralized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants