CSS
.btn-like {
position: relative;
display: flex;
align-items: center;
gap: 10px;
padding: 12px 22px;
border: 1.5px solid #e0dbd3;
border-radius: 50px;
background: transparent;
cursor: pointer;
overflow: visible;
user-select: none;
transition: border-color 0.3s, background 0.3s;
}
.btn-like:hover { border-color: #f43f5e; background: #fff0f3; }
.btn-like-heart {
font-size: 22px;
line-height: 1;
filter: grayscale(1);
transition: transform 0.15s cubic-bezier(.34,1.56,.64,1);
}
.btn-like-count {
display: flex;
align-items: center;
height: 20px;
min-width: 24px;
overflow: hidden;
font-family: ui-sans-serif, system-ui, sans-serif;
font-size: 14px;
font-weight: 600;
color: #888;
transition: color 0.3s;
}
.btn-like.is-liked { border-color: #f43f5e; background: #fff0f3; }
.btn-like.is-liked .btn-like-heart {
filter: none;
animation: btn-like-pop 0.4s cubic-bezier(.34,1.56,.64,1) forwards;
}
.btn-like.is-liked .btn-like-count { color: #f43f5e; }
@keyframes btn-like-pop {
0% { transform: scale(0.8); }
50% { transform: scale(1.4); }
100% { transform: scale(1); }
}
.btn-like-particle {
position: absolute;
font-size: var(--fs, 12px);
line-height: 1;
pointer-events: none;
z-index: 10;
animation: btn-like-fly 0.7s cubic-bezier(.22,1,.36,1) forwards;
}
@keyframes btn-like-fly {
0% { transform: translate(0,0) scale(1); opacity: 1; }
100% { transform: translate(var(--tx), var(--ty)) scale(0.3); opacity: 0; }
}
.btn-like-slide {
display: inline-block;
animation: btn-like-count-up 0.3s cubic-bezier(.22,1,.36,1) forwards;
}
@keyframes btn-like-count-up {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
.btn-like-heart, .btn-like-slide, .btn-like-particle { animation: none; }
} JS
document.querySelectorAll('.btn-like').forEach(function (btn) {
var liked = false;
var count = 2400;
var heart = btn.querySelector('.btn-like-heart');
var label = btn.querySelector('.btn-like-count');
btn.addEventListener('click', function () {
liked = !liked;
btn.classList.toggle('is-liked', liked);
btn.setAttribute('aria-pressed', String(liked));
heart.textContent = liked ? '❤️' : '🤍';
count += liked ? 1 : -1;
var text = count >= 1000 ? (count / 1000).toFixed(1) + 'k' : String(count);
var span = document.createElement('span');
span.className = 'btn-like-slide';
span.textContent = text;
label.innerHTML = '';
label.appendChild(span);
if (liked) {
var cx = heart.offsetLeft + heart.offsetWidth / 2;
var cy = heart.offsetTop + heart.offsetHeight / 2;
for (var i = 0; i < 7; i++) {
var p = document.createElement('span');
p.className = 'btn-like-particle';
p.textContent = '❤️';
var angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI * 1.5;
var dist = 25 + Math.random() * 35;
p.style.left = cx + 'px';
p.style.top = cy + 'px';
p.style.setProperty('--tx', (Math.cos(angle) * dist) + 'px');
p.style.setProperty('--ty', (Math.sin(angle) * dist) + 'px');
p.style.setProperty('--fs', (9 + Math.random() * 7) + 'px');
p.style.animationDelay = (Math.random() * 0.15) + 's';
btn.appendChild(p);
p.addEventListener('animationend', function () { this.remove(); });
}
}
});
});