darkthemetoggle.png

Creating Themes on Any Website


I love dark themes! Every app on my PC and every website that I visit, I use dark theme mode. But how do you actually create one? Or how do we even create more than 2 themes?

Table of Contents

  1. Overview
  2. Creating Toggle
  3. Creating Color Schemes
  4. Adding Functionality
  5. Saving The User Theme Preference
  6. Closing

Overview

I am going to be using one of my projects as an example. I've recently created a calculator app which has 3 themes.

creating-themes-1

You can see that we have a toggle where you can choose between 3 themes.


Creating Toggle

To create toggle you can use a checkbox, radio element or button. In this case I am using radio elements.

<div class="radio">
  <input type="radio" id="theme1" name="theme1" />
  <input type="radio" id="theme2" name="theme2" />
  <input type="radio" id="theme3" name="theme3" />
</div>

Creating Color Schemes

We want to create color schemes using custom CSS variables. You can't use SASS variables! Because SASS variables can't change dynamically. It needs to compile. In this case I will have 3 themes so I need to create 3 schemes. First one will be;

:root {
  --color-main: #3b4664;
  --color-white: #ffffff;
  --bg-main: #181f32;
  --bg-buttons: rgba(37, 45, 68, 0.6);
  --num: #eae3db;
  --number-color: #484b5a;
  --number-border: #b3a599;
  --button-secondary: #647299;
  --border-secondary: #404d70;
  --button-tertiary: #d13f30;
  --border-tertiary: #922417;
  --radio-color: #cf3f34;
}

This is going to be my default theme so I don't need to add any attribute. Second color scheme will be;

body[data-theme="light"] {
  --color-main: #e6e6e6;
  --color-white: #3a3a32;
  --bg-main: #eeeeee;
  --bg-buttons: #d3cdcd;
  --num: #e5e4e0;
  --number-color: #3a3a32;
  --number-border: #a69c93;
  --button-secondary: #388187;
  --border-secondary: #1a5d66;
  --button-tertiary: #c85401;
  --border-tertiary: #873a02;
}

This is going to be our light theme! We want to have a data-theme which has attribute of "light". Data is a special attribute. If you want to learn more check out here. And the last one is;

 body[data-theme="purple"] {
  --color-main: #17062a;
  --color-white: #ffe43b;
  --bg-main: #1e0836;
  --bg-buttons: #1e0836;
  --num: #331b4d;
  --number-color: #ffe537;
  --number-border: #85219b;
  --button-secondary: #56077c;
  --border-secondary: #bf15f4;
  --button-tertiary: #00decf;
  --border-tertiary: #6dfaf1;
  --radio-color: #00e8d8;
}

With this set-up now we can use our variables in our code and after changing the theme colors will change dynamically.


Adding Functionality

First off we want to get our radio buttons in our JavaScript.

const theme1 = document.getElementById("theme1");
const theme2 = document.getElementById("theme2");
const theme3 = document.getElementById("theme3");

Now we want to create changeTheme() function. This function will allow us to change our body attribute so that we can use the right theme.

function changeTheme() {
  if (theme1.checked) {
    document.body.setAttribute("data-theme", "");
  } else if (theme2.checked) {
    document.body.setAttribute("data-theme", "light");
  } else if (theme3.checked) {
    document.body.setAttribute("data-theme", "purple");
  } else return;
}

And now we need to add eventListeners, by doing so;

  1. We want to uncheck other buttons everytime we click one radio button.
  2. We want to trigger changeTheme() everytime we click to corresponding radio buttons.
theme1.addEventListener("click", () => {
  theme2.checked = false;
  theme3.checked = false;
  changeTheme();
});
theme2.addEventListener("click", () => {
  theme1.checked = false;
  theme3.checked = false;
  changeTheme();
});
theme3.addEventListener("click", () => {
  theme1.checked = false;
  theme2.checked = false;
  changeTheme();
});

With this now our themes are fully functional! Whenever user clicks to corresponding theme it will change accordingly.


Saving The User Theme Preference

We have two problems:

  1. There is not any default theme.
  2. User preferred theme is not saved so on every refresh theme goes back to normal

We are going to workaround this by using localStorage

First lets create a default theme.

// My default theme is going to be theme1
if (localStorage.getItem("theme") === null) {
  localStorage.setItem("theme", "theme1");
}

We want to create switch statements so that saved/default theme gets selected every time we refresh the page.

switch (localStorage.getItem("theme")) {
  case "theme1":
    theme1.checked = true;
    break;
  case "theme2":
    theme2.checked = true;
    break;
  case "theme3":
    theme3.checked = true;
    break;
  default:
    break;
}

Then we want to add localStorage.setItem() to make our eventListeners save selected theme to localStorage whenever user clicks to theme buttons.

theme1.addEventListener("click", () => {
  theme2.checked = false;
  theme3.checked = false;
  // New Code
  localStorage.setItem("theme", "theme1");
  changeTheme();
});
theme2.addEventListener("click", () => {
  theme1.checked = false;
  theme3.checked = false;
  // New Code
  localStorage.setItem("theme", "theme2");
  changeTheme();
});
theme3.addEventListener("click", () => {
  theme1.checked = false;
  theme2.checked = false;
  // New Code
  localStorage.setItem("theme", "theme3");
  changeTheme();
});

And lastly we want to call our changeTheme() function every time we refresh the page by adding changeTheme(); to last line.

And voila! We have three themes where user can select one of them and each one is saved using localstorage. With this you can easily create themes to your websites.


Closing

If you want to respect browser/desktop theme settings of user you can easily add prefers-color-scheme using media queries. I didn't want to make this tutorial any longer.

This was my first coding tutorial/blog post so if you have any feedback or opinions feel free to reach me. Thank you for reading I hope this helped you.