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.