Change theme preference of webpage using local storage [HTML/CSS]

Issue

This Content is from Stack Overflow. Question asked by Mark

On this website https://maruko.it there are two buttons on the lower-left corner. Their purpose is to change the webpage’s theme when clicked and save the selected theme for the user in the local storage.

index.html

<head>
...
  <script defer src="/scripts/app.js"></script>
  <link rel="stylesheet" href="/styles/style.css">
...
</head>

<body id='mybody' class='dark-mode'>
  ...
  <span id="v">v1.1 | 
    <span>
      <button id="light-mode">☀️</button>   <!-- changes to light theme -->
      <button id="dark-mode">🌙</button>    <!-- changes to dark theme -->
    </span>
  </span>
  ...
</html>
...

When one of the buttons is clicked, a CSS class gets ‘activated’ (the ‘body’ attribute ‘class’ is changed to either ‘dark-mode’ or ‘light-mode’):

style.css

/* gets activated when button clicked */

:root {
    --white: white;
    --black: black;
}

.dark-mode {
    color: var(--white);
    background-color: var(--black);
}

.light-mode {
    color: var(--black);
    background-color: var(--white);
}

thanks to the following javascript:

app.js

const darkButton = document.getElementById('dark-mode');
const lightButton = document.getElementById('light-mode');
const body = document.body; // won't work without 'defer' attribute

// apply cached on reload
const theme = localStorage.getItem('theme');

if (theme) {
    body.classList.add(theme);
}

// button event handlers
darkButton.onclick = () => {
    body.classList.replace('light-mode', 'dark-mode');
    localStorage.setItem('theme', 'dark-mode');
};

lightButton.onclick = () => {
    body.classList.replace('dark-mode', 'light-mode');
    localStorage.setItem('theme', 'light-mode');
};

On the website you can clearly see that when clicked, the theme changes and gets saved to local storage (on Firefox, check the ‘Storage’ tab) but there’s a catch: if the user selected the ‘light-theme’, on reload there’s always going to be a flash of the ‘dark-theme’. The ‘body’ has now the following attributes:

<body id="mybody" class="dark-mode light-mode">    <!-- now it has both! -->

This is clearly not the intended behavior: it looks like the ‘light-theme’ gets effectively set on the ‘body’ but only after ‘dark-mode’.

Could you please guide me to the right solution / steps to eliminate the problem?



Solution

This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.

This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?