Is there a way to utilize localStorage to retain a classlist toggle status for a light/dark mode theme switch on the browser?

I am currently working on a portfolio website that features a light/dark mode theme switch. The functionality of the switch is working properly, but it doesn't save the user's preference when they refresh the page or navigate to another section. I would like the website to remember the state of the theme selection. I understand that I need to utilize localStorage to achieve this, but I'm having trouble implementing it.

Website: www.hermanvulkers.com

JavaScript code for the theme switch:


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

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

HTML code for the theme switch button:

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

If anyone is able to provide assistance, I would greatly appreciate it. Thank you in advance!

Answer №1

This code appears to be overly complex.

Provided below is a comprehensive version:

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

Answer №2

If you want to incorporate it, follow these steps:

button.addEventListener("click", function () {
    if (document.body.classList.contains("light-theme")) {
        // Switch from light mode to dark mode
        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 {
        // Switch from dark mode to light mode  
        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>`;
        
    }
});

When your site loads initially, ensure you have an event listener to activate or deactivate this feature, like so:

<body onload="setTheme">

In the setTheme function, carry out the following actions:

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

Answer №3

To store an item in the localStorage, you can use the following code:

localStorage.setItem('key', value);

To retrieve the stored item, use:

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

This code should handle the switching between light and dark modes:

    button.addEventListener("click", function () {
    if (document.body.classList.contains("light-theme")) {
        // Switching from light to dark mode
        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 {
        // Switching from dark to light mode  
        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');
        
    }
});

In the beginning of your code, add this snippet:

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>";
}

Answer №4

This function allows you to easily manage the switch state by setting and retrieving it as needed. Instead of checking the state using "if (document.body.classList.contains("light-theme"))", you can simply use the local storage state. Make sure to set the default state to local storage if it is null.

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

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

const removeState = key => localStorage.removeItem(key);

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

Answer №5

Presenting a theme switcher that allows toggling between two or more themes using local storage functionality. Feel free to test it out and reach out if you have any queries! :)

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);
    });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Prevent the onclick function of a span element from being triggered when the user clicks on a dropdown menu contained within

Just delving into the world of web development and currently tackling a React project. Encountered an issue where I need to make a span element clickable. However, there's a dropdown within that span that doesn't have any onClick event attached t ...

What is the best way to apply a filter to an array of objects nested within another object in JavaScript?

I encountered an issue with one of the API responses, The response I received is as follows: [ {type: "StateCountry", state: "AL", countries: [{type: "County", countyName: "US"}, {type: "County", countyNa ...

Locate the div element containing specific text and remove the text from the

Is there a way to locate a div that contains specific text and remove only that specific text from the div? For instance: <div> DeleteText <span>Something text</span> <div>Something span inner text </div> </div> I am l ...

Tips for showing user data following form submission to a SQL database using React JS

Hey everyone, I'm currently working on a project that involves user registration and login. Once the users complete these steps, they are required to fill out an additional form which is displayed below. After submitting this form, the data is stored ...

What is the proper way to retrieve an object from a json file?

My JSON structure looks like this: { "total": 4367, "page": 1, "per_page": 10, "paging": { "next": "/videos?query=second%20world%20war&per_page=10&access_token=XXX&page=2", "previous": null, "first": "/v ...

merging 4 arrays in a specified order, organized by ID

i have below 4 array objects var dataArray1 = [ {'ProjectID': '001', 'Project': 'Main Project 1', 'StartYear': '2023', 'EndYear': '2023', 'StartMonth': 'Sep&apo ...

Incorporate various Vue.js components into the main parent component

I am currently utilizing Vue.js to create a user interface for my HTML5 game. I have a scenario where I want to define UI containers that essentially group other UI components and position them on the screen. Here's an example of what I'd like to ...

What is the best way to trigger a function following a user's selection from a form-control on a webpage?

I am looking for a way to automatically execute a function when a year is selected without needing a button. I am using HTML, JavaScript, and bootstrap 5. Any suggestions on how to achieve this? Thank you. function onSelect() { console.log('Hel ...

I am encountering an issue with the material ui dropdown component in my react native app where I am receiving a TypeError stating that it cannot read the property 'style' of undefined. This error is likely caused

Upon installation of Material UI and importing The Dropdown component, I encountered the error TypeError: Cannot read property 'style' of undefined, js engine: hermes. This is my code import React, { useEffect, useState } from "react"; import { ...

Is there a way to stop the dropdown from automatically appearing in a DropDownList?

Seeking a solution to use a custom table as the dropdown portion for a DropDownList in my project. My goal is for users to see the custom table when they click on the DropDownList, rather than the default dropdown menu. I expected to be able to achieve th ...

Displaying an external webpage within a Backbone application

Is it feasible to display an external webpage in a view by using its URL? I am working with Backbone and Handlebars. var AuthorizeInstagramView = Backbone.View.extend({ template: Handlebars.compile(template), initialize: function () { }, ...

Pass the identical event to multiple functions in Angular 2

On my homepage, there is a search form with an input box and select dropdown for users to search for other users by location or using html5 geolocation. When a user visits the page for the first time, they are prompted to allow the app to access their loca ...

Can Node.js fetch a PHP file using AJAX?

The Challenge: Greetings, I am facing an issue with my website that features a game created using node.js, gulp, and socket.io. The problem arises when I attempt to call a php file from node.js. While the file returns a success message (echo in the file) ...

React.map does not retrieve the specific value

I am facing an issue with my list of items. I have implemented it using mui list, and I have also added a button for editing the list. However, when I click on an item, I am getting the value of the last item instead of the one I clicked on. Below is my f ...

merge a pair of scopes within Angular

I have a dilemma with merging two different scopes. Can someone suggest the most efficient method to achieve this? Here are details of the scopes in question; the second one originates from a service. The initial scope retrieves information from the datab ...

What is causing Mocha.js to be unable to locate the module?

Having trouble with mocha.js not being able to locate my path! Here's the directory structure I have set up for my node course project: ///////Root --package.json --node_modules/ --playground --server -server.js -db -models ...

Adjust font size using jQuery to its maximum and minimum limits

My jQuery script enables me to adjust the font-size and line-height of my website's CSS. However, I want to restrict the increase size to three clicks and allow the decrease size only after the increase size link has been clicked - ensuring that the d ...

Display all data using JSONP

I've encountered an issue with JSONP. Although I was able to successfully load my JSONP data into my html file, I am struggling to display all the information. I have attempted using both a for loop and $.each method without any luck. Here is the JSO ...

changing the core JavaScript of a keyboard plugin

To access the demo, click on this link: . You can find the main javascript file at https://raw.githubusercontent.com/Mottie/Keyboard/master/js/jquery.keyboard.js. Is there a way to switch the positions of the accept and cancel buttons? ...

The Facebook API's JavaScript SDK displays the status as 'connected' even after logging out

As I navigate my AngularJS website, I am utilizing the Facebook SDK for JavaScript to facilitate registration forms. After successfully logging in and retrieving the necessary data from my first attempt, I proceeded to register and eventually logged out of ...