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

CSS + combinator not applied to svelte:elements in #each loop #14890

Open
mlodyga5 opened this issue Jan 4, 2025 · 0 comments
Open

CSS + combinator not applied to svelte:elements in #each loop #14890

mlodyga5 opened this issue Jan 4, 2025 · 0 comments
Labels
css Stuff related to Svelte's built-in CSS handling

Comments

@mlodyga5
Copy link

mlodyga5 commented Jan 4, 2025

Reproduction in Svelte REPL Playground v5.16.1

Describe the problem

When using #each loop, CSS + combinator is not being recognized as used (and thus it's absent in generated CSS):

<script>
  let list = [1, 2 ,3]
</script>

{#each list as value}
  <svelte:element this={'p'}>Style not applied</svelte:element>
{/each}

<style>
  p + p {
    color: red;
  }
</style>
"code": "css_unused_selector"
"message": "Unused CSS selector "p+p" https://svelte.dev/e/css_unused_selector"

But when multiple svelte:element are defined one at a time, it works:

<svelte:element this={'p'} />
<svelte:element this={'p'}>Style applied</svelte:element>

<style>
  p + p {
    color: red;
  }
</style>

If I make it p + p + p in the example above, it shows css_unused_selector too, because it knows there are only 2 unknown elements. Adding a 3rd one makes it happy once again:

<svelte:element this={'p'} />
<svelte:element this={'p'} />
<svelte:element this={'p'}>Style applied</svelte:element>

<style>
  p + p + p {
    color: red;
  }
</style>

Which means that based on multiple defined svelte:element, Svelte seems to be able to recognize that the selector might be applied, so it has to be present in generated CSS.

Why not use :global style?

Two reasons:

  1. Because of how CSS specificity works, :global(p + p) is not applied when there is a style already defined for p in the component:
<svelte:element this={'p'}>Both elements</svelte:element>
<svelte:element this={'p'}>are red</svelte:element>

<style>
  p {
    color: red;
  }

  :global(p + p) {
    /* not applied because of CSS specificity */
    color: green;
  }
</style>

It would require some additional tweaking to make it work, like adding some classes, which seems messy, clumsy and unnecessary.

  1. For my use case, this style belongs to the specific component. It doesn't make sense to make it :global when it is not used anywhere else.

Possible solution

Svelte's understanding of the dynamicity of svelte:element doesn't seem to apply to #each loops. Possibly it's the unpredictability of the number of rendered elements that causes this problem.

One way to handle it would be to disable css_unused_selector altogether when there is svelte:element in #each loop. Possibilities are endless in such case, both in terms of what kind of elements and how many of them will appear. So to me it would make sense allow basically any CSS combinators with any number of elements.

Workaround until it is fixed

Adding multiple svelte:element (even as unreachable code, like below) does the trick:

{#if false}
  <svelte:element this={''} />
  <svelte:element this={''} />
{/if}

To make it work for p + p + p there would have to be 3 of them and so on, so it is obviously not ideal. But at least it's just an additional piece of code that can be easily removed later, when the issue is fixed, without adjusting anything else in the actual code.

There is another thing that I described in the playground where when another component has exactly the same style, it suddenly makes it work in the component with p + p combinator with svelte:element in #each loop. I have already spent much more time than anticipated on describing this though, and maybe it should be placed in another issue anyway, so that's it for now.

Reproduction

Reproduction in Svelte REPL Playground v5.16.1

System Info

Svelte REPL Playground
Version 5.16.1

Severity

annoyance

@dummdidumm dummdidumm added the css Stuff related to Svelte's built-in CSS handling label Jan 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css Stuff related to Svelte's built-in CSS handling
Projects
None yet
Development

No branches or pull requests

2 participants