Density Toggle
A copy-paste theme toggle component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
Theme ToggleHTMLJavaScriptCSSany framework
Copy into your project
HTML
<!-- Density Toggle — Comfortable / Compact, rows re-space via transform -->
<button class="nuda-tt2-density" type="button" aria-pressed="true" aria-label="Toggle layout density">
<span class="nuda-tt2-density__card" aria-hidden="true">
<span class="nuda-tt2-density__row"></span>
<span class="nuda-tt2-density__row"></span>
<span class="nuda-tt2-density__row"></span>
<span class="nuda-tt2-density__row"></span>
</span>
<span class="nuda-tt2-density__label">Compact</span>
</button>JavaScript
/* Density Toggle — toggle aria-pressed and swap the visible label. */
(function () {
var btn = document.querySelector('.nuda-tt2-density');
if (!btn) return;
var label = btn.querySelector('.nuda-tt2-density__label');
btn.addEventListener('click', function () {
var pressed = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', String(!pressed));
if (label) label.textContent = pressed ? 'Comfortable' : 'Compact';
document.documentElement.dataset.density = pressed ? 'comfortable' : 'compact';
});
})();CSS
.nuda-tt2-density {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 6px;
width: 96px;
padding: 10px;
background: rgba(255,255,255,.04);
border: 1px solid rgba(255,255,255,.08);
border-radius: 10px;
color: #cfcfcf;
cursor: pointer;
}
.nuda-tt2-density:focus-visible {
outline: 2px solid #e4ff54;
outline-offset: 2px;
}
.nuda-tt2-density__card {
position: relative;
width: 100%;
height: 56px;
}
.nuda-tt2-density__row {
position: absolute;
left: 0;
width: 100%;
height: 6px;
border-radius: 2px;
background: rgba(255,255,255,.14);
transform: translateY(0);
transition: transform .35s cubic-bezier(.4,0,.2,1),background .3s;
}
.nuda-tt2-density__row:nth-child(2) {
transform: translateY(18px);
}
.nuda-tt2-density__row:nth-child(3) {
transform: translateY(36px);
}
.nuda-tt2-density__row:nth-child(4) {
transform: translateY(54px);
}
.nuda-tt2-density[aria-pressed="true"] .nuda-tt2-density__row:nth-child(1) {
transform: translateY(0);
}
.nuda-tt2-density[aria-pressed="true"] .nuda-tt2-density__row:nth-child(2) {
transform: translateY(11px);
}
.nuda-tt2-density[aria-pressed="true"] .nuda-tt2-density__row:nth-child(3) {
transform: translateY(22px);
}
.nuda-tt2-density[aria-pressed="true"] .nuda-tt2-density__row:nth-child(4) {
transform: translateY(33px);
}
.nuda-tt2-density[aria-pressed="true"] .nuda-tt2-density__row {
background: rgba(228,255,84,.35);
}
.nuda-tt2-density__label {
font: 600 10px ui-sans-serif,system-ui;
color: #a1a1aa;
}
@media (prefers-reduced-motion:reduce) {
.nuda-tt2-density__row {
transition: none;
}
}
How to use Density 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.