DEV Community

WDSEGA
WDSEGA

Posted on

Component Deep Dive #26: Toggle Switch - Zero JavaScript, Pure CSS

Component Deep Dive #26: Toggle Switch

A good toggle works without thinking. A bad one takes three clicks before the user realizes it's interactive.

Core: Checkbox + Label, Zero JavaScript

.toggle__input:checked + .toggle__track {
  background: #6366f1;
}
.toggle__input:checked + .toggle__track .toggle__thumb {
  transform: translateX(20px);
}
Enter fullscreen mode Exit fullscreen mode

The entire animation is driven by :checked. The checkbox itself is hidden with opacity: 0 (NOT display: none - that removes it from the accessibility tree). The label wraps everything, so clicking anywhere toggles the state.

Why Not display: none?

display: none removes the element from the accessibility tree entirely - keyboard users can't Tab to it, screen readers can't see it. Use position: absolute; opacity: 0; width: 0; height: 0; instead: visually hidden, but still in the accessibility tree.

Keyboard Focus

Use :focus-visible instead of :focus - the former only shows the focus ring during keyboard navigation, not on mouse click. This is modern CSS best practice.

RTL Support

In right-to-left languages, the toggle direction should reverse. Use logical properties or [dir="rtl"] selectors.

Common Pitfalls

  1. Forgetting role="switch" - checkbox defaults to role="checkbox", but switch is more semantic
  2. Using display: none - removes from accessibility tree
  3. Hardcoded translateX - must recalculate when changing track/thumb sizes
  4. No disabled state styling - disabled toggles look identical to active ones
  5. transition: all - poor performance, only transition specific properties

The toggle switch proves that with CSS, you can build a fully accessible, animated, interactive component with zero JavaScript.


This article was first published on Deskless Daily. Follow for more AI-driven tech content.

Top comments (0)