What is the best way to incorporate saving the dark/light mode feature to local storage in my application?

The website is currently hosted on a PC, and I've been experimenting with different methods to no avail. Below are the codes that I have implemented. While everything seems to be working fine, there is one issue - whenever I refresh my browser, the mode reverts back to light mode even if the toggle is set to dark mode. It's worth mentioning that I don't have any prior experience with using local storage. Can anyone suggest the best solution that would apply to the codes provided?

<header>
  <div class="controls">
    <p>Light/Dark Mode</p>
    <label class="toggle-switch" for="dark-mode-toggle">
      <input type="checkbox" id="dark-mode-toggle" name="theme" onclick="otherColorChanges()" onreset="restoreDefaultColor()">
      <div class="toggle-switch-border">
        <div class="toggle-switch-dot"></div>
      </div>
    </label>
  </div>
</header>
.toggle-switch {
  display     : inline-flex;
  align-items : center;
  font-family : 'Sora', sans-serif;
  font-weight : 700;
  font-size   : .875rem;
  cursor      : pointer;
  }
.toggle-switch-border {
  display             : inline-flex;
  align-items         : center;
  width               : 60px;
  height              : 36px;
  border              : 1px solid var(--primary); 
  border-radius       : 20px;
  box-sizing          : border-box;
  margin-inline-start : 8px;
  }
.toggle-switch input {
  display: none;
  }
.toggle-switch-dot {
  width         : 28px;
  height        : 28px;
  border-radius : 50%;
  background    : var(--primary);
  transform     : translate3d(3px, 0, 0);
  transition    : transform .1s ease-in-out;
  }
.toggle-switch input:checked + * .toggle-switch-dot {
  transform : translate3d(26px, 0, 0);
  }
body {
  color              : var(--primary);
  font-family        : "Work Sans", sans-serif;
  background         : var(--background);
  /*box-sizing       : border-box;*/
  transition         : color 0.5s;
  transition         : background 0.5s;

  --dark-background  : #253a52;
  --dark-primary     : white; /*#FFFFE3*/
  --dark-link        : #A9FE75;

  --light-background : white; /*#ffffe3*/
  --light-primary    : #253a52;
  --light-link       : #1348da;

  --background       : var(--light-background);
  --primary          : var(--light-primary);
  --link             : var(--light-link);
  }
a {
  color : var(--link);
  }
/* separator bars */
nav,
section {
  border-block-end : 1px solid var(--primary);
  }
/* container for dark-mode toggle */
header .controls {
  display         : flex;
  justify-content : end;
  padding         : 1rem 0;
  margin-right    : 3rem;
  }
 a.btn {
  display         : inline-flex;
  align-items     : center;
  background      : var(--link);
  color           : var(--background);
  text-decoration : none;
  padding         : 0 1rem;
  height          : 2.5rem;
  border-radius   : 1.25rem;
  font-family     : "Montserrat", sans-serif;
  font-weight     : 700;
  font-size       : 0.875rem;
  }
/*Light/Dark mode toggle*/
class CssPropControl {
  constructor(element) {
    this.element = element
  }
  get(varName) {
    return getComputedStyle(this.element).getPropertyValue(varName)
  }
  set(varName, val) {
    return this.element.style.setProperty(varName, val)
  }
}

const bodyCssProps = new CssPropControl(document.body)

let toggle = document.querySelector('#dark-mode-toggle')
toggle.addEventListener('click', () => {
  let mode = toggle.checked ? 'dark' : 'light'
  bodyCssProps.set('--background', bodyCssProps.get(`--${mode}-background`))
  bodyCssProps.set('--primary', bodyCssProps.get(`--${mode}-primary`))
  bodyCssProps.set('--link', bodyCssProps.get(`--${mode}-link`))
})


/*Save dark mode in local storage*/
const darkModeToggle = document.getElementById('darkModeToggle');

darkModeToggle.addEventListener('click', () => {
  darkModeToggle.checked ? document.body.classList.add("bodyCssProps") : document.body.classList.remove("bodyCssProps");
  localStorage.setItem('darkModeStatus', darkModeToggle.checked);
});

window.addEventListener('load', (event) => {
  if (localStorage.getItem('darkModeStatus') == "true") {
    document.body.classList.add("bodyCssProps");
    document.getElementById('darkModeToggle').checked = true;
  }
});

Answer №1

Check your event listeners and how the css variables are being updated. It seems like your localStorage is functioning correctly and the checkbox is properly set on page load, but the variables are only changing when the onClick event occurs.

You have two choices:

  1. Revise your code so that there's a method to update css variables without relying on onClick
  2. Manually invoke darkModeToggle.onClick() after adjusting the checkbox value to trigger the css variable update

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

Tips for excluding two attributes when styling a CSS calendar selection

Let's say I have a table structured like this: <td class="search-unit-custom-control-calendar-day search-unit-custom-control-calendar-day--not-this-month"> <time class="search-unit-custom-control-calendar-day__number">--</time> ...

Arranging items in a vertical column using Bootstrap styling

I am facing a particular issue: The initial design is displayed in Picture 1: I am using Bootstrap 5 as my CSS framework. I attempted to utilize the pre-built columns feature, but so far, I have not been able to find a solution and am currently strugglin ...

What is the most effective method for retrieving a key and value from an Axios response object?

I currently have a Mongoose schema set up to store key:value pairs in a mixed type array, represented like this: Mongoose const budgetSchema = new Schema({ earnings: Number, expenses: [mongoose.Schema.Types.Mixed] }); budget:{ earning:1000, exp ...

Enhance video playback by eliminating accidental scrolling through the space bar

When using a video player, I always prefer to pause it by pressing the spacebar. However, this function is not working as expected. The issue at hand is that instead of pausing the video, pressing the space bar causes the page to scroll down unexpectedly ...

How can I configure a unique error log format in Winston?

I am facing an issue with the default error log format in Winston, as it includes too much unnecessary information such as date,process,memoryUsage,os,trace. How can I remove these unwanted details from the log? logging.js const express = require('e ...

Choosing a row in a table with ASP.NET by utilizing jQuery on click

After setting up a table in ASP.NET with the feature to select individual rows using a link at the end of each row, I have been able to successfully implement it. The process involves setting a value at the top of the view and then dynamically changing the ...

Displaying an array within a method using Vue.js

As a complete newcomer to Vue, I wanted to experiment with methods a bit. Specifically, I attempted to print out an array of strings using the following method: printStringArray(objectWithArray) { i = 0; s = ''; while(i < ob ...

Updating Icons on a Jquery Accordion

I need help modifying an icon to change when clicking on a specific section. Currently, I have the functionality set up to change all accordion icons when opening or closing. However, I am struggling to make it so that only the icon of the selected section ...

Error alert: $.simpleWeather function not found

Currently, I am attempting to incorporate simpleWeather.js from the website simpleweatherjs.com into my own website. However, upon inserting the html code onto my website, an error message pops up: Uncaught TypeError: $.simpleWeather is not a function ...

Is it possible to provide an offset to the raycaster in three.js?

I am currently working on developing a pool game using three.js. As part of the gameplay, I have incorporated a helper ruler that indicates the direction of the hit. This ruler is represented by an ArrowHelper and is positioned at y=0, which aligns with ...

Best practices for using parent and child methods in Vue applications

I'm exploring the most effective approach to creating a modal component that incorporates hide and show methods accessible from both the parent and the component itself. One option is to store the status on the child. Utilize ref on the child compo ...

A meteorological anomaly occurred during the execution of an asynchronous function, resulting in an exception in the

Encountered Problem: I am attempting to update a collection in the onAfterAction hook within a route using the code below (where 'pages' is the name of the collection): var document = pages.findOne({page: "stats"})._id; console.log(document); va ...

What is the best way to retrieve the height of a div that includes an image that has been

I have a script that inserts images into different columns. I want the script to insert images into the column with the smallest height. However, every time I try to check the height of the columns, it always returns 30px (likely because the images are not ...

Keep a collection of completed promises stored in the inventory

Good day, I'm facing a challenge in Parse Javascript where I am trying to save items after receiving them in a loop. However, outside the loop, the array of objects remains empty. .. define global ** var filesUpload = []** for (var key in files) { ...

Which Angular component, directive, or pipe would be best suited for creating dynamic HTML content similar to this?

(I am transitioning from React to Angular, so please bear with me if my question has a hint of React influence.) I am in need of developing an Angular component that can accept a string along with a list of terms within that string for displaying tooltips ...

Incorporating HTML coding into SharePoint Online

Can HTML codes be added to SharePoint Online? I am interested in adding an HTML code from Statista, like the one below: <a href="https://www.statista.com/statistics/262861/uk-brent-crude-oil-monthly-price-development/" rel="nofollow"><img src=" ...

The ng-disable function is not displaying correctly

var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { $scope.firstName = false; $scope.toggle = function(){ $scope.firstName = !$scope.firstName; }; }); <!DOCTYPE html> <html> & ...

Automatic Slideshow

I am trying to implement autoplay in my slider, but I am having trouble figuring out how to do it. The slider itself is working fine, but I know that I need to use an interval for the autoplay feature. If anyone could provide some assistance on how to ac ...

Having trouble positioning the desired image at the bottom of the background using Tailwind CSS

I have been struggling to create a background with a video (z-index -2) and an image overlay (z-index -1). While I have managed to achieve this, I am having trouble getting the image to go all the way to the bottom where the footer is located. I am unsure ...

What is the best way to determine the location of just one element?

I am currently working on a rating application where only the selected circle should remain green, not all of them. $('#rating-container').click(function () { var element = $('#target'); var container = $('#rating-containe ...