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

Importing CSS file in route applies it on hover, and the style is not cleaned up when navigating away from the route #12933

Open
khromov opened this issue Nov 1, 2024 · 6 comments
Milestone

Comments

@khromov
Copy link

khromov commented Nov 1, 2024

Describe the bug

If you do something like import '$lib/layout1.css'; in a +layout or +page, the CSS is incorrectly applied on hover (probably due to the preload functionality).

Additionally when navigating away from the route, the style tag is not properly unmounted, leaving the CSS in place.

For reference, I also included a css import using svelte-preprocess, which shows that scoped CSS does work as intended.

This is a question that has come up many times in the Svelte Discord, and is usually unexpected by the user.

svelte-css.mov

Reproduction

https://github.com/khromov/sveltekit-css-import-repro

npm i && npm run dev

Logs

-

System Info

System:
    OS: macOS 15.0
    CPU: (12) arm64 Apple M2 Pro
    Memory: 212.53 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.8.0 - ~/.nvm/versions/node/v22.8.0/bin/node
    npm: 10.8.3 - ~/node_modules/.bin/npm
    bun: 1.1.25 - ~/.bun/bin/bun
  Browsers:
    Safari: 18.0
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.3.1 
    @sveltejs/kit: ^2.0.0 => 2.7.3 
    @sveltejs/vite-plugin-svelte: ^4.0.0 => 4.0.0 
    svelte: ^5.0.0 => 5.1.9 
    vite: ^5.0.3 => 5.4.10

Severity

annoyance

Additional Information

No response

@benmccann benmccann added this to the 3.0 milestone Nov 1, 2024
@Conduitry
Copy link
Member

Is there anything reasonable to do here besides document it? The many other times this has come up (e.g. #10595), our answer has been that you shouldn't be loading global styles from a component. @benmccann What exactly are you thinking would happen in 3.0?

@khromov
Copy link
Author

khromov commented Nov 1, 2024

Right now workaround seems to be to use svelte-preprocess instead if you want to use a normal css file scoped, but this requires you to change to svelte-preprocess instead of @sveltejs/vite-plugin-svelte which is (imho) not very well documented, and it's not clear what are the upsides and downsides of doing this.

Adding support for the <style src=".."> syntax in @sveltejs/vite-plugin-svelte would go a long way I think, as well as documenting common workarounds, eg if my .css file has a body selector, what should I do with it when migrating vanilla CSS to scoped CSS?

@Rich-Harris
Copy link
Member

Pretty sure this is a wontfix. Importing a .css file in Vite is side-effectful, as it needs to be. If we didn't use Vite's handling and instead injected the styles ourselves (and added a mechanism for tracking which currently mounted components use which styles) the styles would have to exist in JS which is no good.

@theetrain
Copy link
Contributor

theetrain commented Nov 1, 2024

The workaround is to use <svelte:head> and Vite's ?url import hint.

<script>
  import style from '$lib/style1.css?url'
</script>

<svelte:head>
  <link rel="stylesheet" href={style} />
</svelte:head>

This will add and remove stylesheets as you switch in and out of pages using the above code. Also agreed with Vite behaviour since all modules become part of application state the moment they're loaded. Unless there's a way to 'unload' ESM, I don't think that behaviour should change.

@Rich-Harris
Copy link
Member

Note that this workaround will result in FOUC (for client-side navigation) and duplication

@benmccann
Copy link
Member

I feel like we could probably at least catch this during build and issue a warning pointing to some documentation on the issue

I believe we already store a list of which CSS files are used in which layout files. I would kind of expect that we could use that to detect which should be removed when navigating away from a layout, but maybe I didn't catch why that wouldn't work or we don't even want to go down the path of supporting global CSS in components in the first place

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

5 participants