How to Create Simple Toggle Buttons in React

How to Create Simple Toggle Buttons in React

With only a couple of lines of CSS
Ferenc Almasi β€’ 2022 September 16 β€’ πŸ“– 6 min read

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.

Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master React

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>
    )
}
Copied to clipboard!

We will also be using three different props:

  • label: For setting a label for the toggle button
  • toggled: For setting the default state. If left empty, it will default to false.
  • onClick: A click handler for handling onClick 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}
        />
    )
}
The callback function will receive the internal state automatically
Copied to clipboard!

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;
}
Copied to clipboard!

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);
}
Copied to clipboard!

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;
}
Make sure you use the height of the toggle for the line-height
Copied to clipboard!
Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master React

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!

100 JavaScript Project Ideas
Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access exclusive interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Remove ads to learn without distractions
Become a Pro

Recommended