I am building a SSG website that is using SvelteKit (v2.0.0) and Svelte (v5.0.0). I am also using PostCSS using the vitePreprocess
integration.
My project is the default SvelteKit project it generates upon running sv create
with the addition of the SSG adapter, PostCSS and a +layout.svelte
file in src/routes
to apply global CSS properties to the +page.svelte
file in the same directory.
This is what +layout.svelte
looks like:
<script lang="ts">
let { children } = $props();
</script>
<style global lang='postcss'>
@import 'sanitize.css';
:root {
--green: #99dd11;
--blue: #113399;
}
</style>
{@render children()}
In +layout.svelte
's current form, I am using the sanitize.css
npm package. I've also attempted to use the postcss-normalize npm package, replacing @import 'sanitize.css';
with @import-sanitize;
with the same result.
In this current form I am able to use the CSS variables in +page.svelte
I've set, green
and blue
, but the style sheet Svelte generates (both with pnpm run dev
and pnpm run build && pnpm run preview
) does not include any of the styles defined in sanitize.css
. Even when I don't use either variable in +page.svelte
they are still included in the generated CSS file as they are defined in the global scope.
With the included global
in +layout.svelte
's style
tag I was under the impression that sanitize.css
would be applied to every +page.svelte
file in the same directory (and sub directories) as +layout.svelte
.
Furthermore, after reading THIS StackOverflow post I felt that my current code should have worked. I am aware this was made 3 years ago and uses a version of Svelte before v5.0.0.
Here are some other files that might be worth including in finding the solution to this issue:
svelte.config.js
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess([vitePreprocess()]),
kit: {
adapter: adapter({
fallback: '404.html'
}),
paths: {
base: process.argv.includes('dev') ? '' : process.env.BASE_PATH
}
}
};
export default config;
postcss.config.js
import postcssPresetEnv from 'postcss-preset-env';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
const config = {
plugins: [postcssPresetEnv(), autoprefixer(), cssnano()]
};
export default config;
+page.svelte
<style lang="postcss">
p {
user-select: none;
width: 500px;
@media (max-width: 500px) {
width: auto;
}
}
h1 {
color: var(--blue);
a {
transition: all 0.5s;
&:hover {
color: var(--green);
}
}
}
</style>
<h1>Welcome to <a href="https://example.com/">example.com</a></h1>
<p>
This website was built using SvelteKit's static site generator and hosted on Cloudflare Pages.
</p>
Edit: I made a few other attempts to resovle this, none of which worked.
+layout.svelte
to global.css
and only imported global.css
in +layout.svelte
Removing @import 'sanitize.css';
from the <style>
tag and adding import 'sanitize.css';
to the <script>
tag resolves the issue.
I came to this solution when reading the "Where should I put my global styles?" section of the FAQ for vite-plugin-svelte
This pointed out three issues with my original +layout.svelte
file:
Global styles should always be placed in their own stylesheet files whenever possible, and not in a Svelte component's tag
The stylesheet files can then be imported directly in JS and take advantage of Vite's own style processing.
global
attribute in my <style>
tag is a feature from svelte-preprocess, which I was not using or had plans to use. If I were to use global styles in the <style>
tag I should instead use the nested :global { ... }
syntax, which not is recommended for global styles.The fixed +layout.svelte
looks like this:
<script lang="ts">
import 'sanitize.css';
let { children } = $props();
</script>
{@render children()}