Toggle Switch
Create an accessible toggle switch using a checkbox or button with proper ARIA roles and states.
The Bad (Inaccessible)
<div class="toggle-container">
<span>Dark Mode</span>
<div class="toggle" onclick="toggleDarkMode()">
<div class="toggle-thumb"></div>
</div>
</div>
Accessibility-Ready Code
<label class="toggle-switch">
<input
type="checkbox"
role="switch"
aria-checked="false"
id="dark-mode-toggle"
>
<span class="toggle-track">
<span class="toggle-thumb"></span>
</span>
<span class="toggle-label">Dark Mode</span>
</label>
label.toggle-switch
input(
type="checkbox"
role="switch"
aria-checked="false"
id="dark-mode-toggle"
)
span.toggle-track
span.toggle-thumb
span.toggle-label Dark Mode
const [isDarkMode, setIsDarkMode] = useState(false);
<label className="toggle-switch">
<input
type="checkbox"
role="switch"
aria-checked={isDarkMode}
checked={isDarkMode}
onChange={() => setIsDarkMode(!isDarkMode)}
/>
<span className="toggle-track">
<span className="toggle-thumb"></span>
</span>
<span className="toggle-label">Dark Mode</span>
</label>
<label class="toggle-switch">
<input
type="checkbox"
role="switch"
:aria-checked="isDarkMode"
v-model="isDarkMode"
>
<span class="toggle-track">
<span class="toggle-thumb"></span>
</span>
<span class="toggle-label">Dark Mode</span>
</label>
<label class="inline-flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
role="switch"
aria-checked="false"
class="sr-only peer"
>
<span class="relative w-11 h-6 bg-slate-200 rounded-full peer-checked:bg-indigo-600 transition-colors">
<span class="absolute top-0.5 left-0.5 w-5 h-5 bg-white rounded-full shadow-sm transition-transform peer-checked:translate-x-5"></span>
</span>
<span class="text-slate-700 font-medium">Dark Mode</span>
</label>
The Standard
A toggle switch is a specialized control that represents an on/off state. Unlike checkboxes (which are for selection), switches are for immediate actions. Use role="switch" and aria-checked to communicate the state.
WCAG Criteria
- 2.1.1 Keyboard (Level A): Toggles must be operable via keyboard.
- 4.1.2 Name, Role, Value (Level A): The switch role and checked state must be announced.
- 1.4.11 Non-text Contrast (Level AA): The track/thumb must have 3:1 contrast.
β The Bad (Inaccessible)
Whatβs Wrong?
- No Keyboard Access: A
<div>withonclickcannot receive focus. - No Role: Screen readers donβt know this is a toggle control.
- No State: Users cannot tell if itβs currently on or off.
- No Label Association: The βDark Modeβ text is not connected to the control.
β The Good (Accessibility-Ready Code)
Why This Works
- Checkbox Foundation: Uses a real
<input type="checkbox">for native keyboard support. - Switch Role:
role="switch"tells screen readers this is a toggle, not a checkbox. - State Exposed:
aria-checkedannounces the current on/off state. - Label Wrapping: The
<label>element connects the text to the control.
Accessibility Checklist
- Use a real
<input type="checkbox">as the foundation. - Add
role="switch"to indicate toggle behavior. - Include
aria-checkedreflecting the current state. - Wrap in a
<label>or usearia-labelledby. - Ensure the track has sufficient color contrast (3:1 minimum).
- Provide visible focus styles on the control.
<label>
<input type="checkbox" role="switch" aria-checked="true">
<span>Allow Cookies</span>
</label>
Technical Deep Dive
The Accessibility Tree
Role: switch
Name: "Dark Mode"
State: checked / unchecked
Screen Reader Announcements
- VoiceOver (Mac): βDark Mode, switch, offβ
- NVDA: βDark Mode, switch, not pressedβ
Focus Flow
- Tab Key: Captures focus on the hidden checkbox.
- Space Key: Toggles the checked state.
- State Sync:
aria-checkedupdates before visual animation completes.
CSS Technique
The visual toggle is created using CSS on the .toggle-track and .toggle-thumb elements, while the actual <input> is visually hidden but remains in the accessibility tree.
Interactive Behavioral Lab
Interactive Sandbox
π¬ Technical Internals
Understand how this component is processed by the browser and Assistive Technology (AT). This section bridges the gap between visual code and the hidden logic that powers accessibility.
π² Accessibility Tree
The data structure used by screen readers to "see" your page. It translates HTML roles and attributes into standardized objects.
βοΈ Event Logic
Expected behavioral standards for keyboard navigation and state transitions. Crucial for users who don't use a mouse.
- Focus: Highlights via
:focus-visible - Activation: Responds to
EnterandSpace - Role: Identified as
Switch Pattern