A CSS toggle switch generator built on a real checkbox
This CSS toggle switch generator creates the familiar sliding on/off switch without JavaScript. Under the styling is a native <input type="checkbox">, so the switch submits with forms, works with the keyboard (Tab to focus, Space to toggle), keeps its state on the checked property and is announced by screen readers.
Example output
<label class="switch">
<input type="checkbox" role="switch" aria-label="Enable notifications">
<span class="slider"></span>
</label>
The key CSS rules for the default 52 × 30px switch:
.switch .slider::before {
content: "";
position: absolute;
left: 3px;
top: 3px;
width: 24px;
height: 24px;
background-color: #ffffff;
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
transition: transform 0.2s;
}
.switch input:checked + .slider {
background-color: #0f766e;
}
.switch input:checked + .slider::before {
transform: translateX(22px);
}
The full output also includes the track, a rule that hides the input visually and a :focus-visible outline.
How the sizes are calculated
The knob is the height minus the inset on both sides: 30 − 2 × 3 = 24px. When checked it slides by the width minus the knob minus both insets: 52 − 24 − 6 = 22px. Change any of the three values and the travel distance is recalculated, so the knob always stops exactly at the inset.
Options explained
- Width and Height – the track size; keep the width well above the height or the knob has nowhere to travel.
- Knob inset – the gap between knob and track edge.
- On, Off and Knob colours – the track color changes on
:checked. - Shape – Round gives a pill track and circular knob; Square gives slightly rounded rectangles.
- Transition – 0 to 1 second for the knob slide and color change.
Accessibility notes
- role="switch" tells assistive technology to announce "on/off" instead of "checked/not checked".
- Replace the label. The sample
aria-labelmust describe your setting. Better still, add visible text inside the<label>. - Do not use display: none. The input is hidden with
opacity: 0and zero size, so it stays focusable.display: nonewould remove it from the tab order. - State is not color alone. The knob position also shows the state; check the on color against the page in the color contrast checker.
To match a button style, see the CSS button generator; to tune the slide easing, use the cubic-bezier generator.
Privacy
The switch markup and CSS are generated in your browser; nothing is sent to a server.