Six toggle switches written only with Tailwind utility classes. Each uses a real checkbox or radio, hidden with sr-only, and Tailwind's peer and group-has variants to style the visible track, so they need no custom CSS and no JavaScript.
A switch made with Tailwind's peer modifier: the real checkbox is visually hidden with sr-only and marked as peer, and the track and thumb that follow it react with peer-checked: and peer-focus-visible: classes, so no custom CSS is needed.
A switch whose thumb shows a cross when off and a tick when on. Both icons are inline SVGs inside the thumb, and group-has-[:checked]: swaps which one is visible, which lets the parent react to the checkbox inside it without any JavaScript.
A stacked settings card with three rows, each a title, a description and a switch. divide-y draws the lines between rows, and each switch is described by its own text with aria-describedby so the explanation is read aloud.
A wide switch that prints OFF and ON inside the track so the state is never colour-only. The words are two spans positioned at each end; group-has-[:checked]: utilities on the label swap their opacity while the thumb slides across with translate-x.
A Monthly and Yearly segmented toggle built from two radio inputs inside a fieldset. Each label uses has-[:checked]: to become the raised white segment, so the selected option is styled from its own input without peer ordering tricks.
Small, medium and large switches side by side, showing which utilities change between sizes: the track height and width, the thumb size and the translate distance. Keep these three values in step and any size looks right.
Mark the hidden input with peer, then any element after it can react with peer-checked: and peer-focus-visible:. The thumb is drawn with after: utilities on the track and moved with peer-checked:after:translate-x-5.
When peer cannot reach
peer only styles later siblings. To style something nested inside a sibling, such as an icon in the thumb or a word in the track, put group on the label and use group-has-[:checked]:, which reacts to a checked input anywhere inside the group.
Keep the focus ring
Because the input is sr-only, the focus ring has to be drawn on the visible track with peer-focus-visible:ring-2. Without it, keyboard users cannot see which switch is focused.
Production builds
The previews load Tailwind's Play CDN. In a project, install Tailwind with your build tool so only the classes you use are shipped; these classes work in Tailwind v3.4 and later.
Frequently asked questions
Which Tailwind version do these need?
Tailwind v3.4 or later, for the has-[] and group-has-[] variants.
Do they need JavaScript?
No. All six are pure HTML and Tailwind classes.
Is there a plain CSS version?
Yes, see the CSS toggle switches collection for the same ideas without Tailwind.