Primitive
Switch Hybrid
A two-state toggle for settings that take effect immediately. Same underlying <input type="checkbox"> as Checkbox, different visual metaphor and different mental model — flip a switch, the change happens now.
About
Overview
Switches differ from checkboxes in when their state is committed: a switch toggles the setting the moment you flip it, no Save button required. Use them for settings panels, theme toggles, feature flags, and notification preferences. Checkboxes go inside forms; switches go inside settings.
Pair the switch with the label, never standalone. A switch with no surrounding label leaves users guessing what's being toggled. Place the label on the left, the switch on the right.
Live
Demo
<label class="ren-switch">
<input type="checkbox" checked>
<span class="ren-switch-track"></span>
<span>Email notifications</span>
</label>
States
Variants
Reference
API
CSS classes
| Class | Effect |
|---|---|
.ren-switch | The label wrapper. Inline-flex with the input + track + text label. |
.ren-switch-track | The painted toggle. Background fills with the accent color when the input is checked; the thumb slides via transform. |
.ren-switch > input[type="checkbox"] | The native input. Visually hidden but fully accessible. Submits with the form using the input's name. |
No JavaScript or Web Component. Pure CSS adjacent-sibling selectors do the work.
Inclusive by default
Accessibility
Native checkbox semantics. Screen readers announce "checked" / "not checked" — they don't say "switch" by default, which is fine. If you specifically need the "switch" role announced, add role="switch" on the input.
Keyboard
Don't trigger destructive actions on toggle. A switch represents a state change, not a confirmation. If flipping the switch causes data loss, use a Checkbox + Save button or a confirmation Dialog instead.
Patterns
Examples
Settings row
Common pattern: label on the left, switch on the right, optional helper text below.
<label class="ren-switch settings-row">
<span>
<strong>Two-factor authentication</strong>
<span class="settings-row-help">Adds an extra step at sign-in.</span>
</span>
<span>
<input type="checkbox" checked>
<span class="ren-switch-track"></span>
</span>
</label>
Persist on change
document.querySelectorAll('.ren-switch input').forEach(input => {
input.addEventListener('change', async () => {
await fetch('/api/settings', {
method: 'PATCH',
body: JSON.stringify({ [input.name]: input.checked })
});
showToast('Saved.');
});
});