DEV Community

Cover image for How to create a custom Toggle Switch using CSS
Karan Developer
Karan Developer

Posted on • Edited on • Originally published at karankumar.hashnode.dev

How to create a custom Toggle Switch using CSS

Let's create a simple customized toggle switch using CSS. Initially when I was trying to create this, I founded it very confusing because many developers have created this button but none of explain it how is this working.

So after struggling a little bit, I've learned how to create this and I want to share with you all.

I've learned this technique by Marcus Burnette. You can check his Codepen, there are more such interesting pens.

Prerequisite Knowledge

Basics of HTML, CSS (specially Pseudo Elements)


How it works

Button working

As we all know when we assign a label to a input, we can target the input by clicking on label too.

That's what we are going to take advantage of and by this we can convert our label into custom switch which will act same as checkbox.


Let's Start

Workflow

These are the steps that we are going to follow in order to create this button.


1. Create HTML structure

Structure

In this stages we will create the html elements which are input checkbox and a label that is assigned to it but its inner content should be empty.

Reference code is given below.



<!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">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
    <script src="script.js" defer></script>
</head>

<body>

<input type="checkbox" name="switch" id="switch">
<label for="switch"></label>

</body>

</html>



Enter fullscreen mode Exit fullscreen mode

2. Hide the input element

Now we will hide the input element as I said earlier we will make the switch with label element so we don't need the checkbox.




input[type="checkbox"] {
  width: 0;
  height: 0;
  visibility: hidden;
}



Enter fullscreen mode Exit fullscreen mode

3. Style the button body

Button Body

We will create the body of switch or the outer part in which ball will move.

Reference code is given below.



label {
  display: block;
  width: 500px;
  height: 150px;
  background-color: #477a85;
  border-radius: 100px;
  position: relative;
  cursor: pointer;
  transition: 0.5s;
  box-shadow: 0 0 20px #477a8550;
}


Enter fullscreen mode Exit fullscreen mode

4. Create the toggle ball

Toggle Ball

Now we'll create the toggle ball using pseudo element ::after.

Reference code is given below.



label::after {
  content: "";
  width: 120px;
  height: 120px;
  background-color: #e8f5f7;
  position: absolute;
  border-radius: 70px;
  top: 15px;
  left: 15px;
  transition: 0.5s;
}



Enter fullscreen mode Exit fullscreen mode

At this stage our 80% of work is done, now we just have to add the animation to make our switch work.


5. Adding animation

As we know when we toggle the label, checkbox also get toggled.

  • Now we'll add the condition, when checkbox gets checked our ball should be shifted to the right. Slide Animation


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


Enter fullscreen mode Exit fullscreen mode
  • To Change the background on button toggle Background transition



   input:checked + label {
   background-color: #243d42;
   }



Enter fullscreen mode Exit fullscreen mode
  • Now If want a more smooth magnetic effect. When ball get active it its width should increase for a moment. A element gets active when we click on it. We can do this by using :active selector.


    label:active:after {
    width: 160px;
    }


Enter fullscreen mode Exit fullscreen mode

Output Preview

Output


Try Demo


Find Me On

@karancodes Instagram Profile

Top comments (19)

Collapse
 
csmshah profile image
cs-mshah

I have seen many toggle switches. But can you tell me how to design one which can resize easily. like it should have a size similar to the text element before it. If I change the pixels, things start falling apart. Can you write the css in terms of percentage or something and give an example on how to put it next to different sized texts. This would really be very helpful.

Collapse
 
nghh profile image
Jan • Edited

That's exactly what i thought and besides from that, none of those switches handles the actual label with text. So i played around and came up with this one:

codepen.io/nghh/pen/abWKXEK

You just need to edit these variables:

    /* overall size */
    --size: 1.5em;

    /* Finetune switch */
    --height: 2em;
    --width: 4em;
    --border: 0.2em;
    --font-size: 1em;
    --switch-color-checked: darkcyan;
    --switch-color-unchecked: lightgrey;
    --dot-color-checked: white;
    --dot-color-unchecked: white;
Enter fullscreen mode Exit fullscreen mode

Cheers

Collapse
 
csmshah profile image
cs-mshah

yes! this is much better.

Collapse
 
koenahn profile image
Koen Ahn

You could use EM units instead of PX! :) Then change the container's font-size to adapt the switch's size.

Collapse
 
jlopcun profile image
jlop

I don't know why but my label doesnt appear , and after trying my self i copied the code and it still not working ,i dont know why

Collapse
 
karankumardev profile image
Karan Developer

Please share me your Codepen Pen link, I'll definitely look into it !

Collapse
 
jlopcun profile image
jlop

codepen.io/jlopy/pen/KKmeYBK

The css of the label is a copy paste of yours , I only did the firsts steps because its not working , thank you for be helpful

Thread Thread
 
karankumardev profile image
Karan Developer • Edited

First of all, Thankyou for encountering this problem!

Reason
The main difference between your and my code is of Display property. Default property is display:inline;

But I've used flexbox to make my button center to body, In this case body is flex-container and my <label> is flex-item and default display property of flex-items are display:block. And in your case <label> is display: inline;

Solution
Just add display:block in <label>

# Reference code is given below
label {
    display: block;  /* Add this line */
    width: 500px;
    height: 150px;
    background-color: #477a85;
    border-radius: 100px;
    position: relative;
    cursor: pointer;
    transition: 0.5s;
    box-shadow: 0 0 20px #477a8550;
  }
Enter fullscreen mode Exit fullscreen mode

I've also updated my code, Please let me know if you still having any problem.

Thread Thread
 
jlopcun profile image
jlop

My problem is solved , I didn't think that this was the problem , thank you so much

Collapse
 
clementgaudiniere profile image
Clément Gaudinière

Using labels for the switch is very clever and avoids using javascript. Thanks for your tutorial. + 1

Collapse
 
maqbools profile image
քɦʏֆƈօ😈

codepen.io/MaqboolS/pen/qBrwOoG here is something I made but it is not like the toggle switch with path instead its like dark mode/ light mode switch. Hope u all find it usefull

Collapse
 
istealersn profile image
Stanley J Nadar

This is really good but you can also achieve the same with just input element without the label.

Overall, good technique 👍

Collapse
 
httpjunkie profile image
Eric Bishard

You should remix this tortorial or post a codepen, I'd love to see it. I also have a few variations on this same type of toggle but I have it setup as a react component.

Collapse
 
istealersn profile image
Stanley J Nadar

Here is mine (multi-version & animation in progress): codepen.io/istealersn/pen/abWKJbN

Collapse
 
khidersaloum profile image
khidersaloum

It is a nice post to learn

Collapse
 
csorbamatyi profile image
Matyi Csorba

Nice post with pure css!
I made a similar pen about a year ago with background transition
codepen.io/Tyutyesz/pen/VwvNbbZ

Collapse
 
imabhishektomar profile image
Abhishek Tomar

👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏

Collapse
 
denis_billo_3bacbf87a3982 profile image
denis billo

Thank you very much for this CSS!
It works very well for an input...
What if there are 5 inputs in the form?

Collapse
 
denis_billo_3bacbf87a3982 profile image
denis billo

Thank you very much for this CSS!
It works very well for one input, but not with several...
What if there are 5 inputs in the form?