Dark Theme using CSS Variables and Local Storage

Mar 17, 2021


The dark theme has gained prevalence in screens today. With this trend in iOS, macOS, Windows, and Google, most systems have adopted dark themes. Dark theme makes your website more exciting and attractive to users who love a darker color theme. The experience becomes better if you include the functionality to switch between light and dark themes.

This article will help you learn how to implement a switch function between light and dark themes using CSS Variables.

Click this link to find the source code and a runnable program for the implementation.


As a prerequisite, the reader must have a good understanding of the following concepts:

  • Basic Knowledge of HTML, SCSS, and Javascript.
  • Understand CSS variables.

Adding HTML

Let’s begin by building the HTML page that we will use for the tutorial. We will add the theme name and switch id to the checkbox input so that we will need to to refer to it in our javascript.

We are creating a simple webpage consisting of a container, in which we also add a heading, a toggle button, and a paragraph as shown below:

<!DOCTYPE html>
<html lang="en" data-theme="light">
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/main.css">
    <title>Adding dark theme to your site</title>
    <!-- container -->
    <div class="container">
        <!-- heading -->
        <h1>Section Engineering Education</h1>
        <!-- toggle switch contaner -->
        <div class="toggle-container">
            <input type="checkbox" id="switch" name="theme" /><label for="switch">Toggle</label>
            <!-- close toggle switch container -->
            <!-- paragraph -->
        <p>Section partners with university students in Computer Science related fields of study to research and write about topics that are relevant to engineers in the modern technology landscape. You can find more information and program guidelines in the GitHub repository. If you're currently enrolled in a Computer Science related field of study and are interested in participating in the program, please complete <a href="https://docs.google.com/forms/d/e/1FAIpQLSfTbj3kqvEJEb5RLjqJurfbHa8ckzQx0CjRzaizblue9ZOK5A/viewform">this form </a></p>
            <!-- close paragraph -->
       <!-- close container -->
    <script src="main.js"></script>

Output - HTML page

HTML page

Adding CSS

In the same directory as the HTML file, we will add the CSS file that will be used to toggle the default “Light” theme to the “Dark” theme.

I recommend installing a live SCSS Compiler to compile our CSS Code in real-time. You can look into the SCSS compiler’s installation here.

You can change the color code to your favorite color that looks attractive both in dark and light themes.

The CSS styling for the default white theme is:

/* default styling variables - making background color as white */
    --bg: #fff;
    --bg-panel: #ebebeb;
    --color-heading: rgb(27, 168, 14); 
    --color-text: #333333;

The CSS styling for dark theme is:

/* dark theme styling - Here, we set data-them as "dark"*/
html[data-theme='dark'] {
    --bg: #333333;
    --bg-panel: #434343;
    --color-heading: #0077ff; 
    --color-text: #B5B5B5;

Next, we need to specify the CSS styling in the CSS file main.css, so that the website elements will change when we click on the toggle theme button.

body { 
    background-color: var(--bg); /* background color variable */

.container {
  background-color: var(--bg-panel); /* background panel color variable */
  margin: 5em;
  padding: 5em;
  border-radius: 15px;
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 80% auto;
      grid-template-columns: 80% auto;
  -ms-grid-rows: auto auto;
      grid-template-rows: auto auto;
      grid-template-areas: "title switch"
 "content content";

.container h1 {
  margin: 0;
  color: var(--color-heading); /* heading 1 background color variable */

.container p {
  color: var(--color-text); /* text-color variable */
  -ms-grid-column-span: 2;
  grid-area: content;
  font-size: 1.1em;
  line-height: 1.8em;
  margin-top: 2em;

Output After Adding CSS

Output after adding CSS styling

Toggle theme

In the next section, we will style our “Toggle switch” which will helps us switch between the dark and light themes. The code for the toggle button is shown below:

You can find the code to this switch here.

input[type=checkbox] { /* styling for input element */
    height: 0;
    width: 0;
    visibility: hidden;

label { /* styling for labels */
    cursor: pointer;
    text-indent: -9999px;
    width: 52px;
    height: 27px;
    background: #1ba80e;
    float: right;
    border-radius: 100px;
    position: relative;

label:after { /* styling for labels - on toggle */
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    background: #fff;
    border-radius: 90px;
    -webkit-transition: 0.3s;
    transition: 0.3s;

input:checked + label { /* conditional check while toggling */
    background: var(--color-heading);

input:checked + label:after {
    left: calc(100% - 5px);
    -webkit-transform: translateX(-100%);
            transform: translateX(-100%);

label:active:after {
    width: 45px;

Toggle theme switch

Toggle theme

Adding JavaScript

We will handle the theme switching with JavaScript by changing the toggle switch’s class name to either light or dark, as defined below. In doing so, we write two functions changeThemeToDark() and chnageThemeToWhite().

Change the theme to dark

// Change theme to dark by adding the `dark` classname to html element.
const changeThemeToDark = () => {
    document.documentElement.setAttribute("data-theme", "dark")//set theme to light

Change the theme to light

// Reset the html class to default
const changeThemeToDark = () => {
    document.documentElement.setAttribute("data-theme", "light"); //set theme to light

Using local storage

The local storage provides a store for key and value pairs in a browser. Data stores with local storage do not expire even after the browser is closed or refreshed.

The setItem and getItem methods are used to store and retrieve the stored data respectively.

We will use local storage to store our currently set theme, so that in subsequent visits or page refreshes, the users will see their previously set themes.

The pieces of code below are used to save and retrieve the theme from local storage:

let theme = localStorage.getItem('data-theme');
const changeThemeToDark = () => {
    document.documentElement.setAttribute("data-theme", "dark") // set theme to dark
    localStorage.setItem("data-theme", "dark") // save theme to local storage

const changeThemeToLight = () => {
    document.documentElement.setAttribute("data-theme", "light") // set theme light
    localStorage.setItem("data-theme", 'light') // save theme to local storage

After writing the functions, we will check to see what theme is set currently and toggle it.

// Get the element based on ID
const checkbox = document.getElementById("switch");
// Apply retrived them to the website
checkbox.addEventListener('change', () => {
    let theme = localStorage.getItem('data-theme'); // Retrieve saved them from local storage
    if (theme ==='dark'){

Dark Theme

Dark theme webpage


This article has explained how we can implement dark and light themes, and a toggle them to switch, by using CSS variables and localStorage.

You can now try out implementing the dark theme on your own website. You can find the link to the code used in the article here.

Further reading

Happy coding.

Try Launching a Free Project in CloudFlow Today!


Page Transistions in React.js using Framer Motion

Page Transistions in React.js using Framer Motion

React.js framework allows us to create single-page applications (commonly referred to as SPA). A SPA is an application in which the pages do not reload for in-page actions like clicking a hyperlink or clicking a button. The webpage transition is so...

read more
How To Format Form Data as JSON

How To Format Form Data as JSON

The browser Fetch API is used to make requests from a web page on the frontend to an API endpoint on the backend. On the other hand, the browser FormData API provides a precise way of accessing HTML form fields. These two native support browser...

read more