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

Viewed 31

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?

0 Answers
Related