Smooth Toggle
A copy-paste toggles & inputs component in pure HTML & CSS. Zero dependencies, framework-agnostic, MIT-licensed.
Toggles & InputsHTMLCSSany framework
Copy into your project
HTML
<!-- Smooth Toggle — iOS-style toggle switch
Uses a hidden checkbox for native accessibility. -->
<label class="nuda-toggle" role="switch">
<input class="nuda-toggle__input" type="checkbox" />
<span class="nuda-toggle__track">
<span class="nuda-toggle__thumb"></span>
</span>
<span class="nuda-toggle__label">Toggle</span>
</label>CSS
/* ── Smooth Toggle ───────────────────────────────────────────
Customize:
--nuda-tg-w : track width
--nuda-tg-h : track height
--nuda-tg-bg-off : track background (off)
--nuda-tg-bg-on : track background (on)
--nuda-tg-thumb-clr : thumb color
--nuda-tg-gap : thumb padding from track edges
──────────────────────────────────────────────────────────── */
.nuda-toggle {
--nuda-tg-w: 52px;
--nuda-tg-h: 28px;
--nuda-tg-bg-off: #d1d5db;
--nuda-tg-bg-on: #6366f1;
--nuda-tg-thumb-clr: #fff;
--nuda-tg-gap: 3px;
display: inline-flex;
align-items: center;
gap: 10px;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
}
/* Visually-hidden native checkbox */
.nuda-toggle__input {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Track */
.nuda-toggle__track {
position: relative;
display: inline-block;
width: var(--nuda-tg-w);
height: var(--nuda-tg-h);
background: var(--nuda-tg-bg-off);
border-radius: 9999px;
transition: background 0.3s ease;
}
/* Thumb */
.nuda-toggle__thumb {
position: absolute;
top: var(--nuda-tg-gap);
left: var(--nuda-tg-gap);
width: calc(var(--nuda-tg-h) - var(--nuda-tg-gap) * 2);
height: calc(var(--nuda-tg-h) - var(--nuda-tg-gap) * 2);
background: var(--nuda-tg-thumb-clr);
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
transition: left 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Checked state */
.nuda-toggle__input:checked + .nuda-toggle__track {
background: var(--nuda-tg-bg-on);
}
.nuda-toggle__input:checked + .nuda-toggle__track .nuda-toggle__thumb {
left: calc(var(--nuda-tg-w) - var(--nuda-tg-h) + var(--nuda-tg-gap));
}
/* Focus ring for keyboard users */
.nuda-toggle__input:focus-visible + .nuda-toggle__track {
outline: 2px solid var(--nuda-tg-bg-on);
outline-offset: 2px;
}
.nuda-toggle__label {
font-size: 0.9rem;
font-weight: 500;
}
/* ── Accessibility ──────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
.nuda-toggle__track,
.nuda-toggle__thumb {
transition: none;
}
}How to use Smooth Toggle
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.