Skip to content
WebTricks

CSS-only toggle switch

An accessible on/off toggle switch built from a checkbox and a label — no JavaScript.

  • toggle
  • switch
  • checkbox
  • form
  • ui
On color#6b46ff
Off color#3a3f4f
Size28px
HTML
<label class="switch"><input type="checkbox" checked /><span class="slider"></span></label>
CSS
:root {
    --on: #6b46ff;
    --off: #3a3f4f;
    --size: 28px;
}

.switch {
    position: relative;
    display: inline-block;
    width: calc(var(--size) * 1.8);
    height: var(--size);
}
.switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.slider {
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: var(--off);
    cursor: pointer;
    transition: background 0.2s ease;
}
.slider::before {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: calc(var(--size) - 6px);
    height: calc(var(--size) - 6px);
    border-radius: 50%;
    background: #fff;
    transition: transform 0.2s ease;
}
.switch input:checked + .slider {
    background: var(--on);
}
.switch input:checked + .slider::before {
    transform: translateX(calc(var(--size) * 0.8));
}
.switch input:focus-visible + .slider {
    outline: 2px solid var(--on);
    outline-offset: 2px;
}

How it works

A real <input type="checkbox"> keeps it accessible and keyboard-operable; it’s visually hidden, and a <span class="slider"> is styled as the track and knob.

  • The track is the .slider; the knob is its ::before.
  • The :checked + .slider sibling selector flips the track color and slides the knob with a transform — no JavaScript needed.
  • :focus-visible adds a keyboard focus ring.

Everything scales from the single --size variable, and the on/off colors are themeable. Click the switch in the preview to toggle it.