Skip to content

Like Heart

A copy-paste micro-interactions component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

Micro-interactionsHTMLCSSJavaScriptany framework

Copy into your project

HTML
<button class="nuda-like-heart" aria-label="Like" aria-pressed="false">
  <svg class="nuda-like-heart__icon" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
  </svg>
  <span class="nuda-like-heart__particles"></span>
</button>
CSS
/* Like Heart
   Heart fills and bursts particles on click.
   Customize: --heart-color */

.nuda-like-heart {
  --heart-color: #ef4444;
  position: relative;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  outline: none;
}

.nuda-like-heart__icon {
  width: 28px;
  height: 28px;
  fill: none;
  stroke: #888;
  transition: all 0.25s cubic-bezier(0.4, 0.2, 0.2, 1.2);
  will-change: transform;
}

.nuda-like-heart[aria-pressed="true"] .nuda-like-heart__icon {
  fill: var(--heart-color);
  stroke: var(--heart-color);
  transform: scale(1.15);
}

.nuda-like-heart--burst .nuda-like-heart__icon {
  animation: nuda-heart-bounce 0.35s cubic-bezier(0.17, 0.89, 0.32, 1.49);
}

.nuda-like-heart__particles {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.nuda-like-heart--burst .nuda-like-heart__particles {
  background:
    radial-gradient(circle, var(--heart-color) 1px, transparent 1px) 50% 20% / 4px 4px no-repeat,
    radial-gradient(circle, #f59e0b 1px, transparent 1px) 25% 35% / 4px 4px no-repeat,
    radial-gradient(circle, #ec4899 1px, transparent 1px) 75% 30% / 4px 4px no-repeat,
    radial-gradient(circle, var(--heart-color) 1px, transparent 1px) 40% 80% / 4px 4px no-repeat,
    radial-gradient(circle, #f59e0b 1px, transparent 1px) 65% 75% / 4px 4px no-repeat;
  animation: nuda-heart-particles 0.5s ease-out forwards;
}

@keyframes nuda-heart-bounce {
  0% { transform: scale(0.5); }
  50% { transform: scale(1.3); }
  100% { transform: scale(1.15); }
}

@keyframes nuda-heart-particles {
  0% { transform: scale(0.5); opacity: 1; }
  100% { transform: scale(2.5); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .nuda-like-heart__icon { transition: none; }
  .nuda-like-heart--burst .nuda-like-heart__icon { animation: none; }
  .nuda-like-heart--burst .nuda-like-heart__particles { animation: none; }
}
JavaScript
/* Like Heart — vanilla JS
   Toggles aria-pressed and burst animation. */

(function () {
  document.querySelectorAll(".nuda-like-heart").forEach(function (btn) {
    btn.addEventListener("click", function () {
      var pressed = btn.getAttribute("aria-pressed") === "true";
      btn.setAttribute("aria-pressed", String(!pressed));
      if (!pressed) {
        btn.classList.add("nuda-like-heart--burst");
        setTimeout(function () {
          btn.classList.remove("nuda-like-heart--burst");
        }, 600);
      }
    });
  });
})();

How to use Like Heart

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 micro-interactions components

← Browse all NudaUI components