How to make the website's dark mode persistent with Local Storage, CSS and JS

by Tibor Kopca Date: 22-12-2020 javascript webdev css code programming


Recently we wrote about how to do a switchable alternative color mode or theme, a very useful and popular feature to websites. Today’s article is going to be about how to store a user’s settings on your website, specifically, how to save dark mode settings and restore it when a user comes back to your page.

This would be a small update to our previous article about how to make a dark mode theme on your website.

Since web browsers and servers use HTTP protocol which is stateless, something was necessary for the website to “remember” stateful information such as logging in, buttons clicked by user, site preferences, items added into shopping cart, previously entered form fields, etc.

And that something we are going to learn to use.

Why do we need the persistence?

Well the default functionality of browsers is to show the data that comes from a server and it doesn’t store anything - it's stateless. If we have a multi page website or some functionality implemented on our page which will make the page refresh, or simply user hits F5, the page will be set to the default state. That means the JavaScript code for the switch of the color will be set back to default and all changes or configurations made by the user will be lost - the page will look again as freshly loaded - in our case the default color is day theme.

A web developer can implement functionality to remember some data, such as our buttons or previously filled form field, or text size changes for example if needed. And that’s why the local storage or other methods of storing the data are used. With them we can store locally the setting of our button in the browser of the client (on the user’s computer), so every time the user visits or accesses our website he/she would have the button for dark mode in the state it was the last time. The data we want there basically “persist” even when the browser is closed and reopened.

And the knowledge of how to store and keep some configuration of the website on the client's browser is very useful also in other projects, so let's go into it.

Using Local Storage

With Web Storage API mechanisms like localStorage or sessionStorage we can store key/value pairs, in a much more intuitive fashion than using cookies.
 

LocalStorage is similar to sessionStorage, except that while data stored in localStorage has no expiration time, and data stored doesn't get cleared when the page session ends — that is, when the page is closed the sessionStorage data will be cleared in sessionStorage, but localStorage data persists even when the browser is closed and reopened.

So localStorage stores data with no expiration date, and gets cleared only through JavaScript, or clearing the Browser cache / Locally Stored Data, storage limit is the maximum from the three systems - 10MB. For example cookies have only 4kB and sessionStorage 5MB.

Let’s code it!

Last time we showed that with this part of the JS code we manipulate the classes of HTML elements and by that we can set which CSS selectors are being used currently. In short, when the user clicks on the button, the code will toggle between the body has OR has not the class dark and the button class active.

const switchButton = document.getElementById('switch');
 
switchButton.addEventListener('click', () => {
document.body.classList.toggle('dark'); //toggle the HTML body the class 'dark'
switchButton.classList.toggle('active');
//toggle the HTML button with the id='switch' with the class 'active'
});

Now it's time to code the local storage part.


What we need is to check if the ‘dark’ mode is selected, and if not we store the value specifically saying that he has light mode, because if we only store the dark mode value, next time user select the light mode it wouldn't be stored the change and only dark mode would be always be on forever.
This is code for it. We check first if the body has the class ‘dark’ active and then we set the localStorage with method .setItem with two information in it, the key and value - key would be ‘darkMode’ so we know when looking at the information what it represents, and the value would be ‘enabled’ for example.

const switchButton = document.getElementById('switch');
const workContainer = document.getElementById('work');
 
switchButton.addEventListener('click', () => {
    document.body.classList.toggle('dark'); //toggle the HTML body the class 'dark'
    switchButton.classList.toggle('active');//toggle the HTML button with the id='switch' with the class 'active''
    workContainer.classList.toggle('dark');
 
   if(document.body.classList.contains('dark')){ //when the body has the class 'dark' currently
        localStorage.setItem('darkMode', 'enabled'); //store this data if dark mode is on
    }else{
        localStorage.setItem('darkMode', 'disabled'); //store this data if dark mode is off
    }
});

And when we check the website in the browser inspector(after refreshing the page), in the storage tab we can see the information being saved, just like we wanted.

Persistent_Dark_Mode_localstorage_browser_inspector_dark_mode_enabled
How do we know if the user has come to our site again with the information what type of theme he has selected last time? We need to check for this information, with the use of .getItem method of localStorage, like this:

const switchButton = document.getElementById('switch');
const workContainer = document.getElementById('work');
 
switchButton.addEventListener('click', () => {
    document.body.classList.toggle('dark'); //toggle the HTML body the class 'dark'
    switchButton.classList.toggle('active');//toggle the HTML button with the id='switch' with the class 'active''
    workContainer.classList.toggle('dark');
 
    if(document.body.classList.contains('dark')){ //when the body has the class 'dark' currently
        localStorage.setItem('darkMode', 'enabled'); //store this data if dark mode is on
    }else{
        localStorage.setItem('darkMode', 'disabled'); //store this data if dark mode is off
    }
});
 
if(localStorage.getItem('darkMode') == 'enabled'){
    document.body.classList.toggle('dark');
    switchButton.classList.toggle('active');
    workContainer.classList.toggle('dark');
}

Notice that when we check if the ‘darkMode’ has the value ‘enabled’ , this value is not boolean, but of type string, so it needs to be in commas. The check if the dark mode is disabled is not needed, because the page will be loaded by default without the dark mode class.
Another detail is we need to set accordingly the position of the button, for it to represent the correct state, without this we would have a mess with the page in dark mode and the button showing us the light mode is on.


Now it is possible to refresh the page (F5) and not lose the settings we have set on the website. And this is very useful even with other types of settings of the interactive elements. For instance when you need to save something for longer periods of time, like basket information of the e-shop or for storing UI state.


Just a note : If you're interested in syntax which will remove localStorage information we added, it should be like this:

localStorage.removeItem('darkMode');
localStorage.clear(); //The syntax for removing all the localStorage items

Conclusion

This example showed you how we can use Web Storage - specifically Local Storage - to keep information in a user's browser for longer periods of time and exploit this technique to store settings of the visual appearance of our website.
The data or settings will not be deleted when the browser is closed, and will be available anytime the user visits the page again, which allows us to employ interactivity to our site.

We explained how to create JavaScript code to show the state of the website as it was set last time across sessions and device or browser shutdowns, and this client side persistence can be used in a variety of situations.

 
by Tibor Kopca Date: 22-12-2020 javascript webdev css code programming hits : 3174  
 
Tibor Kopca

Tibor Kopca

From tinkering with computers as a teenager, through a career in datacenter he stepped into web development with full force and started coding. Absorbs all information like a sponge.
Fan of aerospace, engineering, information technologies and watches.

 
 
 

Related Posts

Difference between arrow and normal functions in JavaScript

In this tutorial we are going to see how arrow functions differ from normal JavaScript functions. We will also see when you should use one and when you should use…

JavaScript Arrow functions: What they are and how to use them

In this article we are going to see what they are and how to use JavaScript Arrow Functions, a new feature introduced with the ES6 standard (ECMAScript 6). What are Arrow…

How to insert an element into an array with JavaScript

In this brief tutorial you will learn how to insert one or more elements into an array with JavaScript. For this we will use the splice function. The splice function will not…

What is the difference between primitives types and objects in JavaScript?

In this short tutorial we are going to look at the differences between primitive types and objects in JavaScript. To start with, we're going to look at what primitive types…

How to get DOM elements with JavaScript

When you access any element of the DOM, it is usual to save it in a variable. This is something that at first might seem very simple, but if you…

How to reverse an array in JavaScript

In this tutorial we are going to see how you can change the order of the elements of an array so that they are inverted. You could use a loop…

How synchronize the scroll of two divs with JavaScript

In case you have two divs of different sizes you may sometimes want to scroll both at the same time but at different speeds depending on their size. For example,…

Nesting: future proofing CSS

Although not currently supported by browsers, there is a proposal for CSS nesting to support a feature that would provide better readability to native CSS, so in the future it…

How to use the codePointAt method in JavaScript

The JavaScript codePointAt method has more or less the same function as the charCodeAt method, used to get the 16-bit Unicode representation of the character at a certain position in…

How to check if a value is a number in JavaScript

In this short tutorial we are going to look at the various methods that exist to find out if a value is a number in JavaScript.   1. Using the isNaN() function   One…

How to use the charCodeAt method in JavaScript

The charCodeAt method is accepted by strings in JavaScript, returning the 16-bit Unicode code of the character at the position we pass as a parameter to the method. The charCodeAt method…

How to use the charAt method in JavaScript

The charAt method is accepted by strings in JavaScript, returning the position of the character passed as a parameter within the string. If the string contains multiple occurrences of the character…

We use our own and third-party cookies to improve our services, compile statistical information and analyze your browsing habits. This allows us to personalize the content we offer and to show you advertisements related to your preferences. By clicking "Accept all" you agree to the storage of cookies on your device to improve website navigation, analyse traffic and assist our marketing activities. You can also select "System Cookies Only" to accept only the cookies required for the website to function, or you can select the cookies you wish to activate by clicking on "settings".

Accept All Only sistem cookies Configuration