Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to make a toggle switch

Short answer

Take a regular checkbox, remove its default look with appearance: none and draw a track and a knob:

<style>
  .switch { appearance: none; position: relative; width: 44px; height: 24px; margin: 0; border-radius: 999px; background: silver; cursor: pointer; transition: background 0.2s; vertical-align: middle; }
  .switch::before { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: white; transition: translate 0.2s; }
  .switch:checked { background: seagreen; }
  .switch:checked::before { translate: 20px 0; }
  .switch:focus-visible { outline: 2px solid orange; outline-offset: 2px; }
</style>
 
<label><input class="switch" type="checkbox" role="switch" checked> Dark mode</label>

It is still a checkbox: it toggles with a click on the label and with Space, and is submitted with the form. role="switch" tells a screen reader that it is a switch, so it says "on"/"off" instead of "checked".

A disabled switch

:disabled sets the styles for the disabled state:

.switch:disabled { opacity: 0.5; cursor: not-allowed; }

A switch or a checkbox

A switch acts immediately, like a light switch: turn it on — the dark theme appears. If the choice applies only after pressing "Save", a regular checkbox is more familiar.

Common mistake

The switch is built from a <div> and a <span> with a click handler. It does not get focus, cannot be toggled from the keyboard and does not report its state to screen readers. The base must always be an <input type="checkbox"> or a <button>.

Functions used in this recipe

  • <input type="checkbox"> — A checkbox is an independent yes/no choice; a radio button picks one option from a group.
  • appearance — Turns off the built-in look of form controls so they can be styled from scratch.
  • :checked — Matches a checked checkbox or radio button, and a selected `<option>`.
  • ::before — Creates a virtual first child of the element — for decorative text or shapes.
  • transition — Animates the change of a property from the old value to the new one.

Thanks for reading!

Donate to the site — we work hard for you.