How to create a three state toggle switch using HTML, CSS and JavaScript

In this tutorial, I am going to show you how to build a toggle switch with three states.

Normally, a toggle switch has just two states: ON and OFF. That’s why it’s called a toggle switch. However, the other day, while I was browsing the Frontend Mentor website, searching for some frontend development challenges to work on, I came across the calculator challenge on their website.

Working on this challenge required building a toggle switch with three states. The purpose of this switch is to enable users to switch between the three themes of the calculator. While working on this challenge, I found that building out the toggle switch was a little challenging. So, I decided that when I figure out how to build this toggle switch, I will create a tutorial explaining how I did it because I believe there might be others who could benefit from it.

Prerequisites

I will try to explain everything as best as I can. However, having a good understanding of HTML, CSS, and JavaScript will help you go through this tutorial effortlessly.

This is what we are going to be building:

Three State Toggle switch

Let’s begin building!

Create the HTML file

To begin, create the HTML boilerplate with a <div> in the <body> tag to hold three radio buttons.

<!DOCTYPE html>
<html lang="en">
  <head>
    <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="style.css" />
    <title>tri-state toggle</title>
  </head>
  <body>
    <div class="tri-state-toggle">
      <input class="button" type="radio" name="toggle" id="one" />
      <input class="button" type="radio" name="toggle" id="two" />
      <input class="button" type="radio" name="toggle" id="three" />
    </div>
  </body>
  <script src="script.js"></script>
</html>

From the above HTML code, you can see that we have a <div> with a class name of tri-state-toggle, and we’ve also linked to our JavaScript and CSS files.

Style the HTML

If you take a look at our HTML code in the browser right now, you’ll notice that everything looks ugly. To improve the appearance, we need to add some styles.

The goal of applying these styles to the HTML is to:

  • Place the switch at the center of the page.
  • Hide two out of the three radio buttons from the switch.

With these goals in mind, feel free to apply whatever style you like to your HTML.

To begin styling, the first thing you need to do in the CSS file is to remove all the browser-default styles (the default padding and margin that come with the HTML page) to ensure that the styling is consistent.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

Then, center the switch in the body of the page using flexbox.

body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

Concerning the radio buttons, set the height and width of each button to 30px and add a border radius of 50% to make it circular. Then, set the appearance to none to enable you to override the default styling. Finally, add cursor: pointer to the styles to change the cursor on hover.

input {
  height: 30px;
  width: 30px;
  appearance: none;
  background-color: black;
  border-radius: 50%;
  cursor: pointer;
}

The next thing to do now is to style the tri-state-toggle container using flexbox.

.tri-state-toggle {
  display: flex;
  justify-content: center;
  border: 3px solid black;
  border-radius: 50px;
}

Also, add a border and give it a border radius of 50px to make it circular.

Now that we have everything set, we need to make only the first radio button visible and hide the rest of the buttons.

To achieve this, we need to update the style for the radio button by adding opacity: 0 to it.

input {
  height: 30px;
  width: 30px;
  appearance: none;
  background-color: black;
  border-radius: 50%;
  cursor: pointer;
  opacity: 0;
}

Finally, we’ll make the first radio button visible by adding the following:

#one {
  opacity: 1;
}

Complete CSS Code

With everything done, this is how the CSS file would look:

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
input {
  height: 30px;
  width: 30px;
  appearance: none;
  background-color: black;
  border-radius: 50%;
  cursor: pointer;
  opacity: 0;
  cursor: pointer;
}
.tri-state-toggle {
  display: flex;
  justify-content: center;
  border: 3px solid black;
  border-radius: 50px;
}
#one {
  opacity: 1;
}

Add the JavaScript

To begin the JavaScript, we need to query the radio buttons on the HTML page using the getElementsByClassName method:

var buttons = document.getElementsByClassName("button");
var arr = [...buttons];

Notice that we made use of the spread operator to create the arr variable for the buttons. This is because buttons is an HTMLCollection, and the forEach method doesn’t work directly on HTMLCollections. We could have also made use of the for...of statement, but I can’t think of an easy way to get the indexes of the elements using this method.

Next, we would add a click event listener to all the buttons and make it so that whichever button you click will become visible while the rest disappear.

arr.forEach((element, index) => {
  element.addEventListener("click", () => {
    element.style.opacity = "1";

    arr
      .filter(function (item) {
        return item != element;
      })
      .forEach((item) => {
        item.style.opacity = "0";
      });
  });
});

In the above code, after setting the opacity of the clicked button to ‘1’, we go through the array of buttons again to find the remaining buttons (unclicked buttons) by using the filter method and setting their opacities to “0”.

Complete JavaScript Code

Now you can go a step further by using this switch to change the background color of the page by making a few adjustments to the JavaScript code, or you can simply copy and paste the following code into your JavaScript file:

var buttons = document.getElementsByClassName("button");
var arr = [...buttons];

arr.forEach((element, index) => {
  element.addEventListener("click", () => {
    element.style.opacity = "1";
    if (index == 0) {
      document.getElementsByTagName("body")[0].style.backgroundColor = "white";
    } else if (index == 1) {
      document.getElementsByTagName("body")[0].style.backgroundColor = "teal";
    } else {
      document.getElementsByTagName("body")[0].style.backgroundColor =
        "rgb(92, 204, 125)";
    }
    arr
      .filter(function (item) {
        return item != element;
      })
      .forEach((item) => {
        item.style.opacity = "0";
      });
  });
});

And voila! There you have it: a three-state toggle switch! Feel free to play around with the code to better understand it.

three state toggle switch


Written By

Jima Victor

Code lover, crafting cool stuff with JavaScript. Also, geeking out in articles for the tech community. 🚀