Theme Selector
A copy-paste settings & preferences component in pure HTML & CSS. Zero dependencies, framework-agnostic, MIT-licensed.
Settings & PreferencesHTMLCSSany framework
Copy into your project
HTML
<div class="nuda-theme-sel" role="radiogroup" aria-label="Theme">
<label class="nuda-theme-sel__swatch nuda-theme-sel__swatch--light">
<input type="radio" name="theme" value="light" />
<span class="nuda-theme-sel__chip"></span>
<span class="nuda-theme-sel__name">Light</span>
</label>
<label class="nuda-theme-sel__swatch nuda-theme-sel__swatch--dark">
<input type="radio" name="theme" value="dark" checked />
<span class="nuda-theme-sel__chip"></span>
<span class="nuda-theme-sel__name">Dark</span>
</label>
<label class="nuda-theme-sel__swatch nuda-theme-sel__swatch--system">
<input type="radio" name="theme" value="system" />
<span class="nuda-theme-sel__chip"></span>
<span class="nuda-theme-sel__name">System</span>
</label>
</div>CSS
/* Theme Selector
Three swatches in a row, one selected at a time.
Customize: --selected, --swatch-bg */
.nuda-theme-sel {
--selected: #e4ff54;
--swatch-bg: #0c0c10;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.75rem;
width: 100%;
max-width: 420px;
}
.nuda-theme-sel__swatch {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 0.75rem;
background: var(--swatch-bg);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 12px;
cursor: pointer;
transition: border-color 0.2s ease, background 0.2s ease;
}
.nuda-theme-sel__swatch input {
position: absolute;
opacity: 0;
inset: 0;
cursor: pointer;
}
.nuda-theme-sel__chip {
width: 100%;
height: 48px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.08);
}
.nuda-theme-sel__swatch--light .nuda-theme-sel__chip {
background: linear-gradient(135deg, #fafafa, #e4e4e8);
}
.nuda-theme-sel__swatch--dark .nuda-theme-sel__chip {
background: linear-gradient(135deg, #1a1a1f, #09090b);
}
.nuda-theme-sel__swatch--system .nuda-theme-sel__chip {
background: linear-gradient(135deg, #fafafa 0 50%, #1a1a1f 50% 100%);
}
.nuda-theme-sel__name {
color: #a0a0a8;
font-size: 0.75rem;
font-weight: 500;
}
.nuda-theme-sel__swatch:has(input:checked) {
border-color: var(--selected);
background: #111114;
}
.nuda-theme-sel__swatch:has(input:checked) .nuda-theme-sel__name {
color: #fafafa;
}
.nuda-theme-sel__swatch:has(input:focus-visible) {
outline: 2px solid var(--selected);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.nuda-theme-sel__swatch {
transition: none;
}
}How to use Theme Selector
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.