I added dark mode to my Svelte + Tailwind website. I did this by first checking for the user's preferred (system default) theme, but also added a button to change it anytime. I essentially just update the local storage to either store dark or light and then give or remove the class "dark" from the root html element. I have run into an issue though: I give or remove the "dark" class onMount which means the default light theme flashes for a second (blinding anyone within 10km radius) before it changes to dark theme.
Related code (taken directly from Tailwind dark mode guide):
onMount(() => {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
localStorage.theme = 'dark';
} else {
document.documentElement.classList.remove('dark');
localStorage.theme = 'light';
}
});
My question(s):
Is there a way to run a function that checks localStorage and applies the "dark" class before displaying the initial website?
If there is no way to do what I am trying to do, is there any other way I can implement themes with the page rendering correctly right away?
onMount
only runs fairly late on the client.
You could probably also move the logic to a head script in a layout:
<svelte:head>
<script>
...
</script>
</svelte:head>
Such scripts should execute about as early as they can (but you cannot use Svelte features there).