简体   繁体   中英

How can I use localStorage to make the browser remember a classlist toggle state for a light/dark mode theme switch?

I am a working on a portfolio website that has a light/darkmode theme switch. The switch works, but it does not save the input. So when the user refreshes or clicks on a navigation link, the website goes back to the default lightmode. I want it to remember the state. I know that I have to use localStorage to make it work, but I can not seem to figure out how to do it.

Website: www.hermanvulkers.com

JavaScript theme switch code:


button.addEventListener("click", function () {
    if (document.body.classList.contains("light-theme")) {
        // Turn light mode off -> dark mode on
        document.body.classList.toggle("light-theme");
        document.getElementById('themeswitcher').innerHTML = `<span>Dark</span><img src="images/moon.png" alt="Choose website theme">`;

    } else {
        // Turn dark mode off -> light mode on  
        document.body.classList.toggle("light-theme");
        document.getElementById('themeswitcher').innerHTML = `<span>Light</span><img src="images/sunrise.png" alt="Choose website theme"></img>`;
        
    }
});

HTML button code:

<button class="themeswitcher" id="themeswitcher">
    <span>Dark</span>
    <img src="images/moon.png" alt="Choose website theme">
</button>

Is anyone able to help? Thanks in advance!

Your code is unnecessarily complex.

Here is a full version

window.addEventListener("load",function() {
  const theme = localStorage.getItem("theme");
  if (theme) document.body.classList.toggle("light-theme",theme==="light")
  document.getElementById("themeswitcher").addEventListener("click", function () {
    const light = document.body.classList.contains("light-theme")
    this.innerHTML = `<span>${light? 'Dark' : 'light'}</span><img src="images/${light? 'moon' : 'sunrise'}.png" alt="Choose website theme">`;
    document.body.classList.toggle("light-theme");
    localStorage.setItem("theme",light?"dark":"light");
  });
});

You can add it like this:

button.addEventListener("click", function () {
    if (document.body.classList.contains("light-theme")) {
        // Turn light mode off -> dark mode on
        window.localStorage.setItem('darkmodeTurnedOn', 'true');
        document.body.classList.toggle("light-theme");
        document.getElementById('themeswitcher').innerHTML = `<span>Dark</span><img src="images/moon.png" alt="Choose website theme">`;

    } else {
        // Turn dark mode off -> light mode on  
        document.body.classList.toggle("light-theme");
        window.localStorage.setItem('darkmodeTurnedOn', 'false');
        document.getElementById('themeswitcher').innerHTML = `<span>Light</span><img src="images/sunrise.png" alt="Choose website theme"></img>`;
        
    }
});

Also, on initial loading of your site, you should have listener to switch this on or off, like this:

<body onload="setTheme">

And in the setTheme function you can do the following:

function setTheme(){
  if (window.localStorage.getItem('darkmodeTurnedOn') === 'true'){
     document.body.classList.remove("light-theme");
  }
}

You can simply set an item into the localStorage with:

localStorage.setItem('key', value);

and then access it with

let value = localStorage.getItem('key');

So I think this should work:

    button.addEventListener("click", function () {
    if (document.body.classList.contains("light-theme")) {
        // Turn light mode off -> dark mode on
        document.body.classList.toggle("light-theme");
        document.getElementById('themeswitcher').innerHTML = `<span>Dark</span><img src="images/moon.png" alt="Choose website theme">`;
        window.localStorage.setItem('darkMode', 'true');

    } else {
        // Turn dark mode off -> light mode on  
        document.body.classList.toggle("light-theme");
        document.getElementById('themeswitcher').innerHTML = `<span>Light</span><img src="images/sunrise.png" alt="Choose website theme"></img>`;
        window.localStorage.setItem('darkMode', 'false');
        
    }
});

And somewhere in the beginning of your code:

let wasDarkMode = window.localStorage.getItem('darkMode');
if (wasDarkMode) {
document.body.classList.toggle("light-theme");
    

    document.getElementById('themeswitcher').innerHTML = `<span>Dark</span><img src="images/moon.png" alt="Choose website theme">`;
} else {
document.body.classList.toggle("light-theme");
            document.getElementById('themeswitcher').innerHTML = `<span>Light</span><img src="images/sunrise.png" alt="Choose website theme"></img>`;
}

This can be used to set and retvie the switch state. Retrieve it when you need to check the state. Instead of "if (document.body.classList.contains("light-theme"))" you should just use the localstorage state. Just set the default state to localstorage if it is null.

export const set = (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
};

export const retrieve = key => {
    try {
      return JSON.parse(localStorage.getItem(key));
} catch (error) {
    return null;
}
};

export const remove = key => localStorage.removeItem(key);

export const exists = key => localStorage.getItem(key) !== null;

Here is a theme switcher for two or more themes. Working with localstorage. Tell me if it works great and if you have questions. :)

document.addEventListener("DOMContentLoaded", function() {
    var themesList = ['dark-theme', 'light-theme', 'other-theme'];

    var theme = localStorage["theme"] || themesList[0]  /*if localStorage["theme"] exists || default is dark-theme*/;
    const updateTheme = (themeToUpdate = theme)=>{
        switch (themeToUpdate) {
            case 'light-theme':
                document.getElementById('themeswitcher').setAttribute('data-theme', themeToUpdate); // better to use data-* attributes for javascript use only
                document.getElementById('themeswitcher').innerHTML = `<span>Light</span><img src="images/sunrise.png" alt="Choose website theme">`;
            break;
            case 'dark-theme':
                document.getElementById('themeswitcher').setAttribute('data-theme', themeToUpdate);
                document.getElementById('themeswitcher').innerHTML = `<span>Dark</span><img src="images/moon.png" alt="Choose website theme">`;
            break;
            case 'other-theme':
                document.getElementById('themeswitcher').setAttribute('data-theme', themeToUpdate);
                document.getElementById('themeswitcher').innerHTML = `<span>Other</span><img src="whatever/you/want.png" alt="Choose website theme">`;
            break;
        
            default:
            break;
        }    
    } 
    updateTheme(theme);

    button.addEventListener("click", function () {
         let nextIndex = (themesList.indexOf(theme) >= themeList.length - 1) ? 0 : themesList.indexOf(theme) + 1;
        theme = themesList[nextIndex];
        localStorage["theme"] = theme;
        updateTheme(theme);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM