I created a switch button using pure CSS. In this project, the button is a
span
tag, if there is no content between the span tags, span won't show up even with a width and a height values. To make an empty span tag to appear with a colored background, its immediate parent tag should be
display:flex
, otherwise, the
span
has to be
display:inline-block
mode.
For this project, index.html is very straight forward: I use an input
tag with type='checkbox'
, an accompanying label will then wrap around the span
tag, which will be styled for a switch later.
:checked
pseudo element from CSS is used as the condition for on/off switch.
The switch button is working like this: When checkbox is not clicked, which is the state when the page is initially loaded, it looks like this:
When clicking on the button, the
label
that is for the 'checkbox' detects the 'click', change the
:checked
to be true. Then the switch will change to the "ON" state.
The
type='checkbox'
input field has a 13x13px square for user to click to check, this is hidden by setting its position outside of the screen.
How the switch on/off animation is achieved?
After making sure the span
tag has a colored background with a width and a height values, I give it a ::before
and an ::after
psuedo elements. When clicking the button, the ::before
part moves from left to right using translateX
property, the ::after
part has its content changed from "OFF" to "ON" and its absolute position changed from right to left. Transition is also added to make the movement happen smoothly.
Here is the code of index.html and style.scss :
index.html
<div>
<h2>Click to see the switch on/off</h2>
<input type="checkbox" id='btn'>
<label for="btn">
<span></span>
</label>
</div>
style.scss
div {
display: flex;
flex-direction: column;
background: black;
width: 500px;
height: 400px;
margin: auto;
padding: 20px;
align-items: center;
h2 {
color: red;
}
input {
position: absolute;
left: -999px;
}
label {
display: flex;
span {
background: blue;
width: 100px;
height: 30px;
// display:inline-block; // used if div display: flex is missing.
border-radius: 15px;
// for setting position of ::before and ::after psuedo-elements
position: relative;
}
// a circle for switch btn
span::before {
content: "";
position: absolute;
background: red;
width: 50px;
height: 30px;
border-radius: 15px;
transition: transform 0.5s;
}
// off
span::after {
content: "OFF";
color: white;
position: absolute;
right: 14px;
top: 7px;
font-weight: bold;
transition: all 0.5s;
}
}
[type="checkbox"]:checked + label span::before {
transform: translateX(50px);
background: green;
}
[type="checkbox"]:checked + label span::after {
content: "ON";
left: 14px;
}
}