Skip to content

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.

More morphing shapes components

← Browse all NudaUI components