
How to Create Simple Toggle Buttons in React
In this tutorial, we are going to take a look at how you can create simple toggle buttons with the use of the useState
hook and some CSS. By the end of this tutorial, you will have the following buttons ready for you to use in React. Without any further ado, let's jump into creating the component.

Creating the Toggle Button in React
To create a toggle button in React, we will need to use the useState
hook in order to keep track of the state of the toggle internally. To achieve this, we will be using a checkbox to keep the component as accessible as possible.
import { useState } from 'react'
export const Toggle = ({ label, toggled, onClick }) => {
const [isToggled, toggle] = useState(toggled)
const callback = () => {
toggle(!isToggled)
onClick(!isToggled)
}
return (
<label>
<input type="checkbox" defaultChecked={isToggled} onClick={callback} />
<span />
<strong>{label}</strong>
</label>
)
}
We will also be using three different props:
label
: For setting a label for the toggle buttontoggled
: For setting the default state. If left empty, it will default tofalse
.onClick
: A click handler for handlingonClick
events outside of the component.
As you can see, we want to use the toggled
prop as the default state for the useState
hook. If we set it to true
, then the toggle will be toggled by default.
Note that you want to set the defaultChecked
property for the input, rather than using the checked
property. Now is the time to also attach the callback function to the input, where we want to toggle the state, as well as call the onClick
handler with the current state. Now we can call this component in the following way:
import { Toggle } from '@components'
export const App = () => {
const logState = state => {
console.log("Toggled:", state)
}
return (
<Toggle
label="Toggle me"
toggled={true}
onClick={logState}
/>
)
}
Styling the Toggle Button
The toggle button is now functioning, the only thing left to do is to style it in CSS so that it actually looks like a toggle. You might have noticed that we have an empty span
element inside the component.
This is what we are going to display in place of the input
element in order to get a custom look, therefore, you first want to hide the input
, and style the span
.
label {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
input {
opacity: 0;
width: 0;
height: 0;
}
span {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #2c3e50;
transition: 0.3s;
border-radius: 30px;
}
The important part is here that we want to stretch the span
to the size of the label
(60x30). In order to achieve this, we can set all four positions to 0. We can also add a transition
in order to animate the toggle, and for better accessibility, set the cursor
to pointer
so that it's clearly visible it is an interactive element. With all this in place, we should have the following:
In order to add a white circle inside the toggle which will indicate the state, we want to play around with the :before
pseudo-element on the span
. Extend the CSS with the following rules:
span:before {
position: absolute;
content: "";
height: 25px;
width: 25px;
left: 3px;
bottom: 2.6px;
background-color: #fff;
border-radius: 50%;
transition: 0.3s;
}
input:checked + span {
background-color: #00c853;
}
input:checked + span:before {
transform: translateX(29px);
}
Now we have a circle inside the toggle, defined as the :before
element. Give it the same width
and height
, and a border-radius
of 50% to make it a circle. Depending on the size of your toggle, you may want to experiment with the left
and bottom
positions to perfectly position it.
Make sure you don't forget to add a transition
here too, as with the previous transition
, we only animated the background color. Here we animate the position of the circle too. And how can we do that? We need to use the :checked
selector.
If the input is checked, we want to switch the color of our span
, as well as the position of the :before
element. We can grab these using a sibling selector in CSS. All that's left to do is to correctly position the label as well, which we can do with the following rules:
strong {
position: absolute;
left: 100%;
width: max-content;
line-height: 30px;
margin-left: 10px;
cursor: pointer;
}

Final Words
Now you have a custom functioning toggle button created in React, created from a regular checkbox. This not only makes it functioning but accessible too. The code is also hosted on CodeSandbox, so you can reach it here in one piece.
If you are interested in more projects, make sure you check out the article below to find 100 JavaScript project ideas. Thank you for reading through, happy coding!

Access exclusive interactive lessons
Unlimited access to hundreds of tutorials
Remove ads to learn without distractions