Shape Toggle
A copy-paste morphing shapes component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
Morphing ShapesHTMLCSSJavaScriptany framework
Copy into your project
HTML
<!-- Shape Toggle — circle morphs to square on click. JS toggles .is-square -->
<button type="button" class="nuda-morph-toggle" aria-label="Toggle shape" aria-pressed="false">
<span class="nuda-morph-toggle__shape" aria-hidden="true"></span>
</button>CSS
/* Shape Toggle
A circle morphs into a rotated square when .is-square is toggled.
Customize: --morph-toggle-size, --morph-toggle-color */
.nuda-morph-toggle {
--morph-toggle-size: 56px;
--morph-toggle-color: #e4ff54;
background: none;
border: none;
cursor: pointer;
padding: 16px;
outline: none;
}
.nuda-morph-toggle__shape {
display: block;
width: var(--morph-toggle-size);
height: var(--morph-toggle-size);
background: var(--morph-toggle-color);
border-radius: 50%;
transition: border-radius 0.45s cubic-bezier(0.4, 0.2, 0.2, 1.2),
transform 0.45s cubic-bezier(0.4, 0.2, 0.2, 1.2);
will-change: border-radius, transform;
}
.nuda-morph-toggle.is-square .nuda-morph-toggle__shape {
border-radius: 8px;
transform: rotate(45deg);
}
.nuda-morph-toggle:focus-visible {
outline: 2px solid var(--morph-toggle-color);
outline-offset: 2px;
border-radius: 8px;
}
@media (prefers-reduced-motion: reduce) {
.nuda-morph-toggle__shape {
transition: none;
}
.nuda-morph-toggle.is-square .nuda-morph-toggle__shape {
transform: none;
}
}JavaScript
// Toggle the circle <-> square morph
const toggle = document.querySelector(".nuda-morph-toggle");
toggle.addEventListener("click", () => {
const on = toggle.getAttribute("aria-pressed") === "true";
toggle.setAttribute("aria-pressed", String(!on));
toggle.classList.toggle("is-square", !on);
});How to use Shape 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.