sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
77.48k stars 4.04k forks source link

Svelte 5: Cannot use :global() with CSS nesting #10540

Open Pronian opened 4 months ago

Pronian commented 4 months ago

Describe the bug

A compiler error is thrown when using a nested CSS selector with :global(). The nested version of div :global(.b) throws an error, whereas the non-nested version doesn't throw an error.

Reproduction

REPL link

Steps:

  1. Create a component with the following source code:
    
    <div>
    <div class="a">Normal nesting works</div>
    <div class="b">Nesting with :global doesn't work</div>
    <div class="c">Non-nested selector with :global works</div>
    </div>
2. Attempt to compile the component and observe the error
3. Optionally remove/comment the `:global(.b)` selector to confirm that it's causing the issue

### Logs

TypeError: e.selectors is not iterable at eval (compiler.cjs@5.0.0-next.60:1:503253)



### System Info

Svelte 5 Version: Next.60
Happens an all OS-es and in the REPL

### Severity

annoyance
svelte-kit-so-good commented 4 months ago

It works with the & rule

-                 :global(.b) {
+               & :global(.b) {
            color: red;
        }
Pronian commented 4 months ago

@svelte-kit-so-good Good point, I think it would be good to support this without the & as well.

Selectors like div :is(.b) work with nesting and without the &. It's the same syntax.

Pronian commented 2 months ago

I just tested this with the new :global { } feature in v5.0.0-next.111 and unfortunately this issue is still not fixed.

The original issue still generates the same error message and replacing :global() with the new :global { } syntax also produces the same error message.

:global { } syntax version

<div>
    <div class="a">Normal nesting works</div>
    <div class="b">Nesting with :global doesn't work</div>
    <div class="c">Non-nested selector with :global works</div>
</div>

<style>
    div {
        font-family: monospace;

        .a {
            color: blue;
        }

        :global {
            .b {
                color: red;
            }
        }
    }

    div :global {
        .c {
            color: green;
        }
    } 
</style>

REPL

johannesmutter commented 2 months ago

Can confirm. Also weirdly the global { } selector issue not happening in the Svelte 5 REPL but only in a freshly installed sveltekit project in dev mode (?)

:global(...) can be at the start or end of a selector sequence, but not in the middle

    "@sveltejs/vite-plugin-svelte": "^3.1.0",
    "svelte": "5.0.0-next.112",
    "svelte-preprocess": "^5.1.4",
    "vite": "^5.2.10",
    "@sveltejs/kit": "^2.5.7",
Pronian commented 2 months ago

Can confirm. Also weirdly the global { } selector issue not happening in the Svelte 5 REPL but only in a freshly installed sveltekit project in dev mode (?)

:global(...) can be at the start or end of a selector sequence, but not in the middle

    "@sveltejs/vite-plugin-svelte": "^3.1.0",
    "svelte": "5.0.0-next.112",
    "svelte-preprocess": "^5.1.4",
    "vite": "^5.2.10",
    "@sveltejs/kit": "^2.5.7",

In your example it still happens if you use nesting for the .my-div selector as well: REPL

Flunsi commented 1 month ago

UPDATE: I just tested the new :global { } feature for my problem and my problem seems to be solved. However :global() and nesting still breaks and it should be listed more clearly in Breaking changes.

Another bug with :global() and nesting. Perhaps related to this bug. Global works and nesting works, but they dont work together. This example works in Svelte4, but not in Svelte5. For Svelte 5 I have to use the now commented part.

<style>
    :global(h1) {
        background-color: brown;
        &:hover { background-color: chocolate; }
        &.green { background-color: darkgreen; }
        &.green:hover { background-color: forestgreen; }
    }

    /* :global(h1) { background-color: brown; }
    :global(h1:hover) { background-color: chocolate; }
    :global(h1.green) { background-color: darkgreen; }
    :global(h1.green:hover) { background-color: forestgreen; }  */
</style>

Svelte 4 repl - it works

Svelte 5 repl - it doesn't work (reload the page if no code is shown)