How to create a Dark/Light theme toggle

Dark/Light theme toggle

The theme for week #12 of the Weekly Coding Challenge is:

Toggle

A toggle (or a switch) is a component which allows you to change a state / a boolean value from true to false and vice-versa. It is basically a checkbox, but we are going to hide it and display a nicer version of a toggle instead by using a label. 😄

Furthermore, in this article we're going to build a Dark/Light theme toggle:

https://codepen.io/FlorinPop17/pen/ZNqKVM/

The HTML

As mentioned above, we need a checkbox (basically an input with type="checkbox") which we'll hide and a label which will remain visible and it will be styled to look like a toggle (more about these in the CSS section below).

We'll also wrap these elements with a div in order to keep the code more structured.

<div class="toggle">
    <input type="checkbox" id="toggle" />
    <label for="toggle"></label>
</div>

See the for attribute on the label? This is crucial to have because this binds the label to the checkbox with the same id (toggle) and when we click on the label it will trigger the on/off toggle on the checkbox. Pretty neat, eh? 😉

The CSS

First, we'll have to hide the checkbox because it has a default styling that can't really be changed so we are going to style the label instead to look and behave as we want it to:

.toggle input[type='checkbox'] {
    display: none;
}

.toggle label {
    background-color: #777;
    border: 2px solid #555;
    border-radius: 50px;
    cursor: pointer;
    display: inline-block;
    position: relative;
    transition: all ease-in-out 0.3s;
    width: 100px;
    height: 50px;
}

Great! Now we have the oval look on the label; next we're going to use the ::after selector to style the circle which will go inside this oval:

.toggle label::after {
    background-color: #555;
    border-radius: 50%;
    content: ' ';
    cursor: pointer;
    display: inline-block;
    position: absolute;
    left: 2px;
    top: 2px;
    transition: all ease-in-out 0.3s;
    width: 42px;
    height: 42px;
}

We have the styling for the unchecked state. Now let's style the checked state.

Let's change the background and the border colors on the label and the ::after selector (the circle) we are going to move it from left (unchecked state) to the right (checked state) plus we are also changing the background-color for it too.

In order to do that we'll use two selectors:

  1. the :checked selector on the input - this will tell us whether it is checked or not
  2. the ~ or the sibling selector - this will help us target the label tag which comes after our checkbox
.toggle input[type='checkbox']:checked ~ label {
    background-color: #00a0fc;
    border-color: #006dc9;
}

.toggle input[type='checkbox']:checked ~ label::after {
    background-color: #0054b0;
    transform: translateX(50px);
}

Awesome! 😎 Now we finished the HTML and CSS for the toggle. Next, let's play a little bit with JavaScript in order to add and remove a class (.dark-theme) from the body tag. You'll see in a moment why we are doing this...

The JavaScript

const toggle = document.getElementById('toggle');
const body = document.body;

toggle.addEventListener('input', e => {
    const isChecked = e.target.checked;

    if (isChecked) {
        body.classList.add('dark-theme');
    } else {
        body.classList.remove('dark-theme');
    }
});

As you can see, depending on the checked value of the toggle (or checkbox as mentioned above... These terms are interchangeable in our case) we are adding or removing the .dark-theme class from the body.

This can be used now to add some styling on the body depending whether or not it has that class.

Some more CSS

Let's say that by default the body has a light background-color, something like:

body {
    background-color: #f5f7fa;
}

Now, we can target the body with a class of .dark-theme and change the color to a darker grey:

body.dark-theme {
    background-color: #333;
}

This is just a simple example, but in the Codepen that I created you can see that I also added a little bit of text and I'm also changing that text's color based on the value of the toggle. 👍

Conclusion

Now you know how to create a basic dark/light theme toggle. 😃 You can go a step further and add multiple elements on the page (a navbar, sections, a footer, buttons, links, etc) and change their aspect based on the value of the toggle (light or dark... on or off...). Pretty cool, eh? 😉

Can't wait to see what you are going to create!

As always, make sure you share it with me!

Happy Coding! 😇

Tagged with html5, css3, javascript, toggle, switch, after, dark, light, weekly-coding-challenge