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