The 9.9-second source contains four repeated switches across 296 frames. Each state rests for roughly two seconds; the visible transition occupies only six frames.
01 / Setup
Installation
Copy the component stylesheet, then keep the checkbox immediately before its label.
<link rel="stylesheet" href="/theme-switcher.css" />
02 / Anatomy
One state, three moving layers
- The native checkbox owns state and remains available to keyboard and assistive technology.
.theme-switcher__lenscontains the active glass material and its orange light pool..theme-switcher__indicatorfollows the lens while the parent surface crossfades.
03 / Frame analysis
Observed transition phases
The source was sampled at 20fps around both transition directions and checked against the full 30fps capture.
The target state is selected without an anticipation movement.
The full surface passes quickly through a neutral middle gray.
Lens, light pool, and short underline travel as one unit.
Track, icon color, border, and shadow settle into the new material.
04 / Contract
CSS API
| Token / selector | Default | Purpose |
|---|---|---|
--theme-switcher-width | 19rem—31rem | Scales the complete control and icon geometry. |
--theme-switcher-duration | 280ms | Shared lens and indicator travel time. |
--theme-switcher-ease | cubic-bezier(0.22, 1, 0.36, 1) | Fast-out physical settling curve. |
:has(input:checked) | Light state | Lets the surrounding surface react without JavaScript. |
05 / Behavior
Accessibility
The control uses a native checkbox with switch semantics, supports click and Space, exposes a visible focus ring, and removes transition duration when reduced motion is requested.