Building a whole Tailwind app, not just this component?
You just browsed 47 Tailwind toggles switches. Untitled UI Pro unlocks 5,000+ components and sections and 250+ page examples for React, styled with Tailwind CSS v4. One licence is a one-time $349 with lifetime updates; teams start at $999.
The most searched toggle on earth, ported: appearance-none turns the checkbox itself into the 52×32 track, a before: thumb glides across on checked:before:translate-x-5, and active:before:w-8 reproduces the native iOS squash. The port's win is that the resting, on, pressed and reduced-motion states all sit in one class list on the input.
The day/night switch, ported whole: the thumb is a glowing sun that morphs into a crescent via a single inset box-shadow transition, stars fade in, a cloud drifts out — and the surrounding panel re-themes itself through has-checked:, the utility form of :has(:checked).
Dual-source lighting as utilities: the track is carved INTO the surface with two inset shadows, the knob extrudes out of it with two outset shadows, and active:before:scale-90 presses it physically into the pit before it glides across.
The blob that necks and snaps: an inline feGaussianBlur + feColorMatrix chain fuses a thumb with a trailing echo, and the only thing Tailwind has to do is move them — has-checked: on the track, a delay-[90ms] on the echo, and the filter draws the liquid between them.
Premium motion from one token: --ease-ttg05-spring in @theme mints an ease-ttg05-spring utility whose negative first control point winds the thumb backwards before it shoots across and bounces off the far wall. One transition, no keyframes, no spring library.
State spelled out, not inferred: ON and OFF live inside a 96px track, the thumb covers the inactive word, and the active one fades in. The port is a peer masterclass — one sr-only checkbox drives a track, two words and a thumb, all through peer-checked:.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
The billing switcher every pricing page ships: two sr-only radios, a highlight pill that glides behind the active label, a save badge, and a price that live-swaps underneath — all from peer-checked: and one has-checked: on the card. Radios mean arrow-key navigation comes free.
A bank of mechanical keycaps that latch: each cap travels down into its socket on press, stays seated and backlit when on, and fires an 8ms navigator.vibrate tick on hardware that supports it. The stem is a solid shadow-[0_7px_0_...] that shortens as the key bottoms out.
A mute switch that shows sound instead of describing it: five bars dance while audio is live and snap to a flatline the instant you mute. --animate-ttg09-eq in @theme mints the animate-ttg09-eq utility; per-bar delays stay inline, because a stagger is data, not a design token.
A switch that disarms itself: flip it on and a conic ring drains for 8 seconds, then the toggle flips back off with the change announced politely. The ring is a registered custom property the browser tweens natively — no requestAnimationFrame loop anywhere.
A destructive-action guard shaped like a fingerprint sensor: press and hold 1.2s while a scan line sweeps and a ring fills. Release early and it disarms. The state lives on aria-checked, so the styling variant and the accessibility contract are literally the same attribute.
An airport departure-board cell that flips between OFF and ON: the top half hinges down over the bottom in real 3D, revealing the new word exactly like a mechanical split-flap. Four half-height layers, one rotate-x-180, zero JavaScript.
A settings card that reads its own children: a stack of permission rows, and a header badge that flips between Full access, Partial and No access purely by watching the group with :has(). This is the modern replacement for the classic "JavaScript counts the checkboxes" widget — a state machine that cannot desync from the DOM.
A spec-faithful Material 3 switch in utilities: a 52×32 outlined track, a thumb that grows 16 → 24 → 28dp as it slides and presses, a checkmark that fades in on the handle, and the M3 state-layer halo blooming on hover and focus.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
A wall-plate rocker with a bevelled plate, slotted screws and a paddle that tips in real perspective — and when you flip it the whole room warms from dusk to lamp-light, because the section watches the switch with has-checked:.
A clipped-corner neon tube for dark dashboards and game UIs: magenta standby snaps to cyan on engage, and the LIVE legend strikes like a gas tube warming up. Every glow is layered box-shadow and text-shadow — no images, no filters.
Anti-animation as a statement: 3px black borders, a hard 6px offset shadow, and a block thumb that does not glide — it SNAPS across in a single frame via ease-[steps(1,end)]. Pressing shoves the whole card into its own shadow.
A wide cinematic switch that IS a landscape: the sun sets behind clip-path mountains as the moon climbs the mirrored path, stars fade in, the ridges darken, and the page follows the scene into night. The most shareable control in the collection.
A boolean as a physical object: the whole control rotates 180° to reveal its other face — muted "Paused" on the front, vivid "Active" with a live figure on the back. v4's first-class 3D utilities mean the entire flip is five classes.
The label rides in the thumb: a wide pill whose sliding handle says "Draft" or "Live", crossfading its word mid-journey while ghost labels in the track show where a click will take you. Built for publish switches, where the state word must move with the control.
A frosted-glass switch floating over a vivid scene: backdrop-blur-[14px] backdrop-saturate-150 on the pane, a denser frost puck for the thumb, and two drifting gradient blobs behind it that visibly refract through both as it slides.
A machined aluminium knob that twists between OFF and ON detents: brushed-metal conic sheen, a milled indicator, bezel tick marks and a pilot LED that ignites at the ON position. The checkbox IS the knob — click or press Space to twist it.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
The whole iOS Settings context, not just the switch: a grouped light list with inset hairlines, coloured glyph tiles and three native-geometry toggles — the pattern to copy when you need an entire preferences screen, section header and footnote included.
A stroke-only switch drawn entirely in currentColor: hollow track, hollow thumb that fills solid when on. Because it inherits colour from surrounding text, the identical markup works on a white card, a dark card and a brand banner with zero per-theme CSS.
A river pebble instead of a circle: the asymmetric blob squashes as it launches, stretches mid-flight and wobbles back into shape on landing. Two --animate-* tokens — one for checking, one for unchecking — because a transition cannot sequence anticipate → stretch → settle.
The power switch off the back of real hardware: a rectangular rocker with engraved I and O halves seesawing inside a riveted steel panel, and a red pilot lamp that ignites on power. Perspective, gradients and text-shadow do all the machining.
The reference implementation to ship in a design system: button[role=switch] with correct aria-checked handling, visible state text, a spec-grade focus ring — and it stays fully visible in Windows High Contrast, where most CSS toggles silently vanish.
Demo 08's keycap idea taken to a six-key macro pad: a 3×2 grid of latching keys over an RGB underglow that blooms through the chassis gaps, each key showing its shortcut, and a live count of what is armed. Denser, louder, and it scans in one glance.
The waveform idea rebuilt as studio hardware: a radial VU meter whose needle sweeps while audio is live and drops to the peg when muted, over a masked conic arc that runs green through amber to red. Same job as demo 09, a completely different read.
The auto-off idea made countable: instead of a smooth ring, ten pips extinguish one per second, so the remaining time is a number you can read at a glance. Discrete beats read as urgency in a way a sweeping arc never does.
The hold-to-confirm guard rebuilt as a gesture: drag the handle the full width of the rail to arm, let go early and it springs back. A shimmer sweeps the hint text while it waits, and the whole thing is operable with arrow keys.
The split-flap's mechanical cousin, rebuilt without 3D: a word stack rolls vertically behind a slotted window, with gradient shadows at the top and bottom edges selling the curve of a drum. Cheaper than a 3D flip and it reverses perfectly.
What demo 13 could not do: a master switch that actually SETS the group, with a real third state. When some children are on, the master goes indeterminate — a dash, not a thumb — using the native pseudo-class and aria-checked="mixed".
Settings as tiles, not rows: a 2×2 quick-settings grid where the whole tile is the switch — it fills with its accent when on, dims to frosted glass when off, and dips under the finger. The touch target is 150×80, so nobody misses.
M3's other switch: a connected group of icon toggle buttons where each segment is independently on or off, the ends are fully rounded, and a selected segment fills with the secondary container tone and grows a check. Multi-select, not a radio group.
Two switches on one plate, and the room responds to BOTH: one on is a dim pool of light, two on floods the scene. Counting children in pure CSS is the trick — :has() can test combinations even though it cannot count.
Demo 16's neon, but the light moves: a registered <angle> property spins a conic gradient around the frame, masked into a 2px border, so an armed switch has a single point of light running its perimeter. The chase IS the on state.
Checking it stamps: a rotated APPROVED block slams down over the card with a scale-and-settle keyframe, borders 3px, shadow hard and offset. Where demo 17 snaps a thumb, this one commits an act — the state looks like a decision that was made.
A dark-mode switch with weather: flip it and three blurred aurora ribbons drift across a deep sky at different speeds while the horizon cools. Demo 18 moves objects; this one moves atmosphere, which is a different kind of quiet.
A solid object, not a card: two faces of a cube joined at a real edge, rotating 90° so the switch has actual thickness. v4's translate-z-* makes this the first Tailwind version where a cube needs no custom CSS at all.
Not every setting is binary: a three-detent selector for Off / Auto / On, where the thumb travels to thirds and the card below explains what the chosen mode actually does. Named peers make three positions no harder than two.
Glass with a lens in it: the thumb brightens and saturates what sits behind it, carries a moving specular sweep across its crown, and drags a soft caustic shadow along the track. Demo 21 frosts a pane; this one bends light.
Demo 22's knob with somewhere to go: three radio-driven detents at −50°, 0° and 50°, tick marks that light as the pointer reaches them, and a mode readout under the dial. A knob with two positions is a switch; a knob with three is a knob.
The mute slider off the side of a phone: a knurled grip that slides in a machined channel and reveals a painted orange band behind it. No thumb glides — it travels in a slot, and the colour underneath is what tells you the state.
A switch that shows what it buys you: turning on low-power mode recolours the battery amber and extends the projected runtime from 4h 10m to 6h 45m, with the estimate bar physically growing. The consequence is the interface.
One SVG becomes two icons: the sun's rays retract into their own centres via stroke-dashoffset while a mask circle slides in to bite a crescent out of the disc. No icon swap, no second file — the same eight paths morph.
The finale: a red safety cover you must flip up before the switch beneath can be thrown, exactly like the guarded toggles on aircraft panels. Two deliberate actions, a warning strip that wakes up, and closing the cover kills the switch automatically.
FAQ
Frequently asked questions
How does the iOS-style toggle in demo 01 turn a plain checkbox into a switch?
The trick is appearance-none on the <input type="checkbox"> itself, which strips the native tick box so you can size and paint the element as the whole track. In demo 01 the input becomes a 52px pill; a pseudo-element or a sibling <span> acts as the thumb, and the checked state slides it with peer-checked:translate-x-full when the label wraps a peer input, or with checked: variants directly on the input. Because it is still a real checkbox, it submits with a form, toggles on Space, and exposes a checked state to assistive tech for free. Two things to keep: give it a paired <label> so the whole pill is clickable, and set an explicit width and height — an appearance-none checkbox collapses to near-zero intrinsic size, so a missing dimension is why your track renders as a sliver.
Why does my :has() status badge in a permission group never update?
Demo 13 and demo 33 read their own children with :has() — the card header flips a badge when has-[:checked] or the more precise has-[input:checked] matches a descendant. Three things break it. First, :has() looks at the DOM subtree, so the toggles must actually be inside the element carrying the variant, not siblings of it. Second, the inputs must be real form controls that hold a :checked state; a <div> painted to look checked will never match. Third, a fully custom appearance-none checkbox still reports :checked, but if you hid it with display:none some engines drop it from matching — use sr-only or appearance-none with zero opacity instead. For the tri-state master in demo 33 you also need the :indeterminate state, set in script via the element's indeterminate property since no attribute or utility expresses it.
What is the accessible way to build these when the control is a button, not a checkbox?
Demo 27 is the reference: a <button type="button"> with role="switch" and aria-checked toggled between true and false in the click handler. Use this shape when the toggle acts immediately on state rather than submitting inside a form. The rules: the button needs an accessible name — visible text or aria-label — and it must respond to both Enter and Space, which a real button does natively (a <div> with a click listener does not). Never animate away the focus ring; keep a visible focus-visible: outline. The demo also ships forced-colors support so the track and thumb stay distinguishable in Windows high-contrast mode, where your background colours are discarded — draw the on/off distinction with a border or the thumb position, never colour alone, or the switch becomes a single flat block that reads identically in both states.
How does the gooey morphing switch in demo 04 make the thumb neck and snap?
It is the classic gooey filter: an inline <svg> defines a filter with feGaussianBlur to soften edges into a haze, then feColorMatrix ramps the alpha channel hard so anything below a threshold vanishes and anything above snaps to solid. Applied to a container holding the track blob and the moving thumb, two shapes that overlap during the slide fuse into one surface that necks and pinches — the liquid look. The gotcha is that the filter lives in real SVG markup you must keep in the DOM; a Tailwind filter utility cannot express this chain, so the element references it via filter:url(#id). Two failure modes: the filter needs a solid backdrop because blur over a transparent area bleeds a grey fringe, and the blur is genuinely expensive, so keep the filtered subtree tiny. If you only need a bounce, demo 05's spring easing is far cheaper than paying for a per-frame blur.
The conic border light in demo 37 won't animate — the gradient just sits there. Why?
A conic gradient's angle is not animatable on its own; the browser has no way to interpolate a raw <angle> buried in a background string. Demo 37 fixes this by registering a custom property as a real typed angle with @property, giving it syntax:"<angle>", an initial value and inherits:false. Once the property is typed, the keyframe can transition it from 0deg to 360deg and the conic gradient reads that variable, so the light appears to sweep. The usual bug is declaring the variable with a plain --angle:0deg — that is a string as far as animation is concerned and stays frozen. It must go through @property. Same mechanism drives the conic countdown ring in demo 10. Note @property is a fairly recent feature; behind it, gate the motion with @supports or accept a static border on older engines rather than a broken one.
How do the SaaS pricing toggle (demo 07) and three-position selector (demo 41) track state without JavaScript?
Both use grouped <input type="radio"> controls hidden with sr-only, wrapped in <label> elements so clicking a word checks the matching radio. The sliding highlight is a single absolutely-positioned pill whose translate-x is driven by which radio is :checked, using sibling combinators or peer-checked: variants — Monthly sits at 0, Annually slides one segment over. Demo 41's Off / Auto / On is the same idea at thirds, the thumb travelling to 33% and 66%. Radios matter because they enforce mutual exclusion for free: one name, one checked at a time. The common mistake is forgetting to share a single name across the group, which lets two segments check at once and leaves the highlight stranded between them. Keep the labels focusable and arrow-key navigable — a native radio group already moves selection with the arrow keys, so don't intercept them.
The frosted glass toggle in demo 21 shows no blur — it's just a flat translucent pill. What's wrong?
backdrop-blur samples whatever is painted behind the element, so it only shows an effect when there is content underneath to blur. Demo 21 floats the switch over a vivid scene; drop the same pill on a flat solid page and there is nothing to sample, so you see a plain semi-transparent shape. Three requirements: the element needs a translucent background — a fully opaque fill hides the blurred layer entirely — plus backdrop-blur-[14px] and, in the demo, backdrop-saturate-150 to deepen the colours it pulls through. The classic bug is an ancestor with overflow:hidden and a transform or filter, which establishes a new stacking context and clips the backdrop source, killing the blur. Also note backdrop-filter is a compositing cost on every paint, so reserve it for a real glass surface over imagery, not a switch sitting on a solid card where a normal translucent fill looks identical.
When should I not use the flashier toggles like the split-flap, cube, or gooey ones?
Treat demos 12, 40, 04, 08 and their kin as feature moments, not utility controls. A 3D split-flap or rotateY cube toggle is delightful once on a landing page or a settings hero, but a form with fifteen of them is exhausting and slow — the perspective transforms and, for the gooey filter, the per-frame blur all cost paint work. For a dense settings list, ship the plain appearance-none switch from demo 01 or the iOS grouped rows from demo 23. Two hard limits regardless of style: every continuous or bouncy animation must collapse under motion-reduce: variants so a user who set reduce motion gets an instant state change, not a spin; and each control still needs a real checkbox or a role="switch" button underneath, keyboard-operable and labelled. If a demo's charm depends entirely on a hover or a long animation to reveal its state, it fails on touch and for reduced-motion users — pick a quieter one there.