Authoring and importing global CSS
There are a few ways to write global or classic CSS classes without generating scoped CSS hashes.
Note this recipe was authored with Svelte 5 and SvelteKit 2 in mind.
Summary of methods
| Method | Behaviour |
|---|---|
import './styles.css' |
CSS file is loaded via <link /> appended to <head> when component mounts. It does not get removed when component unmounts. |
@import './styles.css' within <style> |
Prepends './styles.css' inline with component CSS |
<svelte:head><link rel="stylesheet" href={stylesheet} /></svelte:head> |
CSS file is loaded via <link /> appended to <head> when component mounts. It does get removed when component unmounts. |
:global() |
Does not scope selectors defined inline within a component <script>. Styles are added or removed from CSSOM with component lifecycle. |
:global {} |
Same as :global(), but applies to nested selectors. |
<style global> |
Same as :global {}, but applies to all selectors within <style>. Requires a preprocessor. |
ESM import (Vite)
<script>
import './styles.css'
</script>
- When component mounts, imported styles are appended once to the
<head>and will remain there even when the component unmounts or re-mounts. - Whether or not the page is prerendered, ESM-style imports will eagerly load in
SvelteKit (see
data-sveltekit-preload-data). - In the production build, Vite will convert the file name
styles.cssto a generated and hashed name for cache busting.
CSS @import (Vite)
<p>Hello world</p>
<style>
@import "./style.css";
</style>
- At build time, imported styles are prepended to the component's stylesheet output.
- When component mounts, component styles are appended to
<head>and remain there even when the component unmounts or re-mounts. - Whether or not the page is prerendered, component styles with or without using
@importwill eagerly load in SvelteKit. - When component unmounts, all component styles remain in
<head>and kept in the CSSOM.
Manually adding stylesheets via <svelte:head>
<script>
import stylesheet from './styles.css?url'
</script>
<svelte:head>
<link rel="stylesheet" href={stylesheet} />
</svelte:head>
- At build time, Vite will detect explicit url
imports (
?url) and generate a hashed filename forstyles.css, and store the asset filename in the default module assignment (stylesheetin the example above). - When the component mounts,
<link rel="stylesheet" href={stylesheet} />gets appended to the<head>. - When the component unmounts,
<link rel="stylesheet" href={stylesheet} />gets removed from the<head>. - This is useful for theming or lazy-loading styles. Though consider adding
stylesheets with this method in your root
+layout.sveltealong with themediaattribute.
Svelte Global styles, inline :global()
<script>
import Input from '$lib/Input.svelte
</script>
<p>Hello world</p>
<div class="input-wrapper">
<Input />
</div>
<style>
:global(p) {
color: crimson;
}
/*
Scoped global selector trick, this only affects
styles for elements wrapped with your scoped selector.
*/
.input-wrapper :global(input) {
border-color: green;
}
.input-wrapper {
/*
Optional, remove wrapper from box model.
Should be used with discretion and on presentational
elements only.
*/
display: contents;
}
</style>
:global()marks any wrapped selectors to not received scoped classnames from Svelte.- Be cautious since component CSS remains in the CSSOM once mounted, and broad
selectors wrapper with
:global()may affect other elements on the page. - One trick to target wrapped elements and write global selectors that won't
impact styles outside the component is to wrap child components with an
element and give that a scoped class with a
:global()marker on the selector's tail. - When using the scoped wrapping selector trick, use
display: contentswith discretion.
Reference: https://svelte.dev/docs/svelte/global-styles.
Svelte Global styles, :global {} block
<p>Hello world</p>
<style>
:global {
p {
color: crimson;
}
}
p {
/*
This has higher specificity than the global selector
and the paragraph will render with green text.
*/
color: green;
}
</style>
Reference: https://svelte.dev/docs/svelte/global-styles.
Internal use
Although there are a few ways to author 'classic' CSS selectors without scoped CSS, it's not necessary to do so when styling components you control and author. Svelte provides a built-in way to scope styles that work with the cascade.
For example:
src/lib/styles.css
/* Global links, (0,0,0) specificity for other global overrides */
:where(a) {
color: crimson;
}
src/routes/+page.svelte
<script>
import '$lib/styles.css'
</script>
<p>
Check out this new recipe!
<a href="#some-area">Bread recipe</a>
</p>
<style>
/*
(0,1,1) specificity after scoped classes are generated
inherits `color: crimson` from global CSS since `a` is still selectable
*/
a {
font-weight: bold;
}
</style>