A <label class="switch"> wrapping
<input type="checkbox"> is the control. The
label text is a sibling of the input — no
.lever required. They are CSS only. There is no
JavaScript component and nothing to AutoInit.
Tokens follow the
M3 switch spec.
The track is 52×32dp. Unselected is
surface-variant with a 2dp outline and
a 16dp handle. Selected is a primary track and a
24dp on-primary handle. The state layer is 40dp at
8% hover and 10% focus. The touch target is 48dp. The label is
body-large / on-surface. Disabled is
38%.
<label class="switch">
<input type="checkbox">
Wi-Fi
</label>
<label class="switch">
<input type="checkbox" checked>
Bluetooth
</label>
<label class="switch">
<input type="checkbox" disabled>
Airplane mode
</label>
An input + span or input + .lever still
works if you already have that markup.
The on/off captions are decoration. Left as bare text they are folded
into the label, and the switch announces itself as “Off On” — so hide
them and name the control itself. A switch whose only text is a
caption needs an aria-label, because hiding both leaves
it with no name at all.
<label class="switch">
<span aria-hidden="true">Off</span>
<input type="checkbox" aria-label="Dark mode">
<span class="lever"></span>
<span aria-hidden="true">On</span>
</label>