Seamless/Flicker-Free Theme Switching in Svelte-kit
Following are some steps you can follow to implement/fix theme screen flickering on page reload/load. These methods can be adapted to any framework.
Step 1: Create a store for managing theme state:
import { writable } from 'svelte/store';
const isBrowser = typeof window !== 'undefined';
const storedTheme = isBrowser ? localStorage.theme : null;
const theme = writable(storedTheme || 'system');
if (isBrowser) {
theme.subscribe(v => {
localStorage.theme = v;
});
}
export { theme };
Step 2: In +layout.svelte subscribe to
the theme store created in the previous step and update the
document.body
class list to the current value of the store.
<script>
import { theme } from '$lib/stores/theme';
import { onMount } from 'svelte';
onMount(() => {
theme.subscribe(v => {
const bodyClassList = document.body.classList;
bodyClassList.remove('light', 'system', 'dark');
bodyClassList.add(v);
});
});
</script>
Step 3: Add your preffered method for theme switching:
<div class="header">
<select bind:value={$theme} class="theme-selector">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
Step 4: Create a stylesheet.css file and define CSS variables for light and dark themes using the prefers-color-scheme media query.
/* Define light theme styles */ @media screen and (prefers-color-scheme: light) { :root { /* Light theme CSS variables */ } body.dark { /* Override specific styles for the dark theme */ } } /* Define dark theme styles */ @media screen and (prefers-color-scheme: dark) { :root { /* Dark theme CSS variables */ } body.light { /* Override specific styles for the light theme */ } }
Step 5: In app.html, set the initial theme class on document.body based on the stored theme or user's color scheme preference.
<body data-sveltekit-preload-data="hover">
<script>
const storedTheme = localStorage.getItem('theme');
const systemPreferredTheme = window.matchMedia(
'(prefers-color-scheme: dark)'
).matches ? 'dark' : 'light';
document.body.classList.remove('light', 'dark');
document.body.classList.add(
storedTheme ?? systemPreferredTheme
);
</script>
</body>
2023-08-01
by Zed Kaido