20 CSS Link Hover Effect Designs 08 / 20
Heartbeat Pulse
A leading dot pulses with a real medical-grade heartbeat rhythm — lub-DUB-pause-lub-DUB-pause via a multi-keyframe @keyframes.
The code
<a href="#" class="cle-heartbeat"> <span class="cle-heartbeat-dot" aria-hidden="true"></span> <span>Live updates</span> </a>
<a href="#" class="cle-heartbeat">
<span class="cle-heartbeat-dot" aria-hidden="true"></span>
<span>Live updates</span>
</a>.cle-heartbeat {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 4px 6px;
color: #f0eeff;
font:
600 15px/1.2 system-ui,
sans-serif;
text-decoration: none;
border-bottom: 1px solid transparent;
transition:
border-color 0.25s,
color 0.25s;
}
.cle-heartbeat-dot {
position: relative;
width: 9px;
height: 9px;
border-radius: 50%;
background: #ff3d6e;
animation: cle-heartbeat-thump 1.6s ease-in-out infinite;
flex-shrink: 0;
}
.cle-heartbeat-dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: inherit;
animation: cle-heartbeat-ring 1.6s ease-out infinite;
}
.cle-heartbeat:hover,
.cle-heartbeat:focus-visible {
color: #fff;
border-bottom-color: rgba(255, 61, 110, 0.5);
}
/* Real heartbeat curve: lub (small bump) → DUB (big bump) → long pause */
@keyframes cle-heartbeat-thump {
0% {
transform: scale(1);
}
10% {
transform: scale(1.18);
}
20% {
transform: scale(1);
}
30% {
transform: scale(1.32);
}
45% {
transform: scale(1);
}
100% {
transform: scale(1);
}
}
@keyframes cle-heartbeat-ring {
0% {
transform: scale(1);
opacity: 0;
}
30% {
opacity: 0.55;
}
100% {
transform: scale(3);
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.cle-heartbeat-dot,
.cle-heartbeat-dot::after {
animation: none;
}
} .cle-heartbeat {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 4px 6px;
color: #f0eeff;
font:
600 15px/1.2 system-ui,
sans-serif;
text-decoration: none;
border-bottom: 1px solid transparent;
transition:
border-color 0.25s,
color 0.25s;
}
.cle-heartbeat-dot {
position: relative;
width: 9px;
height: 9px;
border-radius: 50%;
background: #ff3d6e;
animation: cle-heartbeat-thump 1.6s ease-in-out infinite;
flex-shrink: 0;
}
.cle-heartbeat-dot::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: inherit;
animation: cle-heartbeat-ring 1.6s ease-out infinite;
}
.cle-heartbeat:hover,
.cle-heartbeat:focus-visible {
color: #fff;
border-bottom-color: rgba(255, 61, 110, 0.5);
}
/* Real heartbeat curve: lub (small bump) → DUB (big bump) → long pause */
@keyframes cle-heartbeat-thump {
0% {
transform: scale(1);
}
10% {
transform: scale(1.18);
}
20% {
transform: scale(1);
}
30% {
transform: scale(1.32);
}
45% {
transform: scale(1);
}
100% {
transform: scale(1);
}
}
@keyframes cle-heartbeat-ring {
0% {
transform: scale(1);
opacity: 0;
}
30% {
opacity: 0.55;
}
100% {
transform: scale(3);
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.cle-heartbeat-dot,
.cle-heartbeat-dot::after {
animation: none;
}
}