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: noneto remove the default styling and then are set to fill the container evenly - an
::afterpseudo-element on the<fieldset>to create a circular switch clip-pathand:hasset 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-schemeattribute 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.