Unable to save the current light/dark mode preference to local storage

Being a beginner in JavaScript, I am currently working on implementing a simple light mode button for my website which defaults to dark mode. The transition between JS/CSS dark and light modes is seamless, giving the site an appealing look when switching to light mode.

However, I have encountered an issue where the current CSS mode is not saved in local storage. This results in the default dark mode being displayed when users navigate to a different HTML page.

Despite researching numerous articles and forum posts, as well as testing various code samples, I have been unsuccessful in finding a solution. Below, you'll find snippets of my JS code along with a portion of my HTML/CSS.

My main question is: How can I modify the code to ensure that the current Dark/Light Mode setting is stored in local storage and accessed upon page reload or switching?

Thank you in advance for your assistance! :)


 /* Light mode css */

body {
  font-size: 21px;
  font-family: Tahoma, Geneva, sans-serif;
  max-width: 550px;
  margin: 0 auto;
  background-color: white;
}
h1 {
font-size: 30px;
color: white;
text-align: center;
text-shadow: 0px 0px 5px black;
margin: 40px 0 20px 0;
}
h2 {
font-size: 20px;
color: black;
text-align: center;
}
.btn-toggle {
background: white;
}

 /* Dark mode css */

body {
  font-size: 21px;
  font-family: Tahoma, Geneva, sans-serif;
  max-width: 550px;
  margin: 0 auto;
  background-color: black;
}
h1 {
font-size: 30px;
color: white;
text-align: center;
text-shadow: 0px 0px 5px black;
margin: 40px 0 20px 0;
}
h2 {
font-size: 20px;
color: white;
text-align: center;
}
.btn-toggle {
background: white;
}

<!-- First HTML page -->

<!doctype html>
<html lang="en-gb">
<head>

   <link rel="stylesheet" type="text/css" href="darkmode.css" id="theme-link">
   
</head>

<body>

<h1>Toggle Dark/lightmode example</h1>

<button class="btn-toggle">Toggle dark/light</button>
<a href="test2.html"><button>Go to Site 2</button></a>

<h2>Unnecessary content</h2>

<script type="text/javascript" src="darkmode.js"></script>


<!-- Second page -->

<!doctype html>
<html lang="en-gb">
<head>

   <link rel="stylesheet" type="text/css" href="darkmode.css" id="theme-link">
   
</head>

<body>

<h1>Toggle Dark/lightmode example</h1>

<button class="btn-toggle">Toggle dark/light</button>
<a href="test1.html"><button>Go back to Site 1</button></a>

<h2>Unnecessary content</h2>

<script type="text/javascript" src="darkmode.js"></script>

<script>

// The JS file is usually eternally linked

// Select the button
const btn = document.querySelector(".btn-toggle");
// Select the stylesheet <link>
const theme = document.querySelector("#theme-link");
const currentTheme = localStorage.getItem("theme");
if (currentTheme == "dark") {
  document.body.classList.toggle("dark-theme");
} else if (currentTheme == "light") {
  document.body.classList.toggle("light-theme");
}

btn.addEventListener("click", function() {
  
  if (theme.getAttribute("href") == "kiblsstyle.css") {
    theme.href = "kiblsstylelight.css";
  } else {
    theme.href = "kiblsstyle.css";
  }
  localStorage.setItem("theme", theme);
});
</script>

</body>
</html>

Answer №1

Storing the entire HTML element in local storage is not recommended. Instead, consider storing the theme name and applying the theme conditionally based on what is stored locally. Below is a cleaned-up version of your JavaScript code:

const btn = document.querySelector(".btn-toggle");

const styleLink = document.querySelector("#theme-link");

// Retrieve stored theme with fallback value
const currentTheme = localStorage.getItem("theme") || "light";

if (currentTheme === "dark") {
    styleLink.href = "kiblsstyle.css";
} else if (currentTheme === "light") {
    styleLink.href = "kiblsstylelight.css";
}

btn.addEventListener("click", () => {
    if (styleLink.getAttribute("href") !== "kiblsstyle.css") {
        styleLink.href = "kiblsstyle.css";
        localStorage.setItem("theme", "dark");
    } else {
        styleLink.href = "kiblsstylelight.css";
        localStorage.setItem("theme", "light");
    }
});

Answer №2

localStorage was initially designed for storing basic, primitive values and is not meant to store DOM elements. In your case, you can simply save a boolean value for the theme selection, with just two options. (If more themes are added, consider using multiple buttons or an array). Avoid saving DOM objects when switching theme titles.

Check out this article on localStorage


const theme = document.querySelector("#theme-link");
const currentLightTheme = localStorage.getItem("isLight") || true;

btn.addEventListener("click", function() {
    if (!currentLightTheme) {
        theme.setAttribute('href', 'kiblsstylelight.css');
    } else {
        theme.setAttribute('href', 'kiblsstyle.css');
    }
    
    localStorage.setItem('isLight', !currentLightTheme)
});

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

The functionality of Selection.modify is unfortunately limited when it comes to input and textarea elements in Firefox

Check out this demonstration (jsfiddle link): const input = document.querySelector('#input'); const textarea = document.querySelector('#textarea'); const div = document.querySelector('div'); const x = (e) => { if (e.ke ...

How to utilize DefinePlugin in Webpack to pass NODE_ENV value

I am attempting to incorporate the NODE_ENV value into my code utilizing webpack through the use of DefinePlugin. I have reviewed a similar inquiry on Stack Overflow, but I am still encountering issues. Here is the configuration I am working with: In pac ...

Strategies for testing a split get() function using expressJS and jestJS to streamline unit testing

How can I define a get() route in an Express.js application for easy unit testing? To start, I extracted the get() function into its own file: index.js const express = require('express') const socketIo = require('socket.io') const Gp ...

Looking to include a new item into an array with the help of AngularJS

Having just started with angularJS, I am facing difficulties in adding an object from a form to an array. When I click on "Add New Product", it triggers the "newItemModal". I enter the new product information but the submit button doesn't seem to work ...

Creating and launching multiple tabs in node.js (cloud9 IDE): A step-by-step guide

I am currently working on a choice provider. This program will take a (choice) program with a variable number of choices. For example: Let's say we want to make a coffee with two choices - 1. <light, dark> ...

Transform jQuery code into vanilla JavaScript

I'm struggling with converting this part of code from jQuery to plain JavaScript. I've documented everything in a JSFiddle as an illustration. The following is the script: $(".button").click(function () { $pageID = $(this).attr('name& ...

Leveraging API JSON information in conditional return statements with React

Working on a small Express/React app (not for production), I am validating a hashed pin in express and returning either message: false if validation fails or message: <cardnumber> if validation is successful. Currently, in my react frontend, I am try ...

Revamp responsiveness in bootstrap 3 for printing with @media queries

My goal is to disable the responsive features of bootstrap when the event javascript:print() is triggered. This way, I want my webpage to maintain the column grid layout that I have defined, regardless of screen size. One solution suggested in this answer ...

Hiding elements with CSS using the display:none property and using the :

Trying to display an image when hovering over another image. Works well in Safari, but Chrome and Firefox fail to load the image properly. Have searched for solutions related to visibility:hidden but none seem to solve this cross-browser issue. HTML being ...

Using JavaScript Regular Expressions to locate all prefixes leading up to a specific character

Consider a scenario where you have a string consisting of terms separated by slashes ('/'), like this: ab/c/def Your goal is to identify all the prefixes of this string up to a slash or the end of the string. For the given example, the expected ...

I'm encountering an error when trying to use makeStyles

Something seems off with MUI. I was working on my project yesterday and makeStyles was functioning properly, but now it's suddenly stopped working. I'm encountering an error when calling it here: https://i.sstatic.net/tBf1I.png I suspect the iss ...

Choosing specific text below an element

I'm having trouble selecting specific text from the table below <section id="bullet_features"> <h2>Additional Features</h2> <p> Knife Steel: 8Cr13MoV, satin finish <br> Handle: Molded co-polymer <br> Blade: 3.6 in. ...

The dropdown-menu-end class in Bootstrap 5 navbar is not activating on hover as expected

My Bootstrap navbar has right-aligned dropdowns, but when I try changing the trigger to hover, the .dropdown-menu-end class doesn't work as expected. I attempted using CSS for the hover effect: .dropdown:hover .dropdown-menu { display: block; mar ...

Ways to define a variable based on a CSS class attribute?

I need help figuring out how to create a variable in my script that is defined by the width attribute of a CSS class. The snippet I have currently doesn't seem to work as expected. var dist = $('.nav').css(width()); The goal of my script i ...

Is the unit test for attribute failure specific to running it on only one node?

I am currently using Enzyme and Jest to verify the presence of an id attribute in a dropdown list. import React from "react"; import { mount } from "enzyme"; import ListPicker from './ListPicker.js' describe("ListPicker", () => { let props ...

How to align text to the right with ellipsis and button in a ReactJS component

In a specific scenario, I need to display a button on the right corner of the header. The selected filter value should appear next to the filter button like this: | Between 01/23/2018 and 07/30/2018 {button}| As the user changes the screen size, I want to ...

What is the best way to retrieve a value by using the data.get() method?

I am currently facing an issue with retrieving the value of a textarea that I have dynamically added to a fieldset in my form. When I attempt to submit the form, the code below is executed: function handleSubmit(e) { e.preventDefault(); console.log( ...

Attempting to scroll through a webpage and extract data using Python and Selenium in a continuous manner

Recently, I posed a question (you can find it here: Python Web Scraping (Beautiful Soup, Selenium and PhantomJS): Only scraping part of full page) that shed light on an issue I encountered while attempting to scrape all the data from a webpage that updates ...

Troubleshooting: Bootstrap 5.0 Navbar Dropdown Issue Unresolved

My navbar dropdown isn't working when clicked. I've searched for solutions without success. Is there a script missing? layout.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> ...

The interval keeps resetting every time I want the initial one to expire first

I'm currently working on a battle system that utilizes intervals, and I've encountered an issue where it keeps refreshing instead of creating multiple intervals. When I stop pressing the button associated with it, everything goes back to normal. ...