Sometimes you need to toggle between three values but most off-the-shelf component libraries don’t cover this use case. Changing color themes between system and light/dark is a common use case.
The purpose-built HTML form element to use is the <input type="radio">
element. A group of radio elements with a common name
property will allow only one radio element to be checked at a time, with a unique value associate with each input. However, the default styling of radio elements leaves something to be desired, e.g.:
Fortunately, using the exact same markup, a <fieldset>
and three <input type="radio">
elements, each with a <label>
, you can easily implement a three-way switch with CSS.
- the fieldset forms the switch container
- input elements have
appearance: none
to remove the default styling and then are set to fill the container evenly - an
::after
pseudo-element on the<fieldset>
to create a circular switch clip-path
and:has
set the position of the switch based on which radio input is checked- the labels are positioned absolutely and visually hidden by default, but shown when the corresponding radio input is checked
- custom
linear()
easing function makes the switch feel springy - an event listener on the
<fieldset>
updates thecolor-scheme
attribute on the<html>
element when the radio input is changed
Bringing it all together:
See the Pen 3 way switch by Sam Breed (@wookiehangover) on CodePen.
There’s also (at the time of writing) a three-way toggle in the footer of this website.