12 CSS Ripple Effects07 / 12
CSS Heartbeat Pulse Ripple Effect
A cardiac monitor UI — a large animated heart icon with three concentric fill-pulse rings and two stroke rings, a looping SVG ECG trace with animated stroke-dashoffset, vital-signs stat tiles and a blinking LIVE indicator. All pulse timing matches a 72 BPM heartbeat rhythm. Nunito on deep maroon-black.
Published
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<div class="rpl-07">
<div class="rpl-07__bg" id="rpl-07-bg"></div>
<div class="rpl-07__header">
<h1>Heartbeat Pulse Ripple Effect</h1>
<p>CSS keyframe animation with multi-wave pulse rings and ECG trace</p>
</div>
<div class="rpl-07__hero">
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__heart">❤️</div>
<div class="rpl-07__bpm"><b>72</b> BPM</div>
</div>
<div class="rpl-07__ecg">
<div class="rpl-07__ecg-label">ECG · Lead II</div>
<svg viewBox="0 0 560 64" preserveAspectRatio="none">
<path class="rpl-07__ecg-line"
d="M0,32 L40,32 L48,32 L52,28 L56,32 L60,32 L66,8 L70,60 L74,20 L78,32 L84,32
L124,32 L132,32 L136,28 L140,32 L144,32 L150,8 L154,60 L158,20 L162,32 L168,32
L208,32 L216,32 L220,28 L224,32 L228,32 L234,8 L238,60 L242,20 L246,32 L252,32
L292,32 L300,32 L304,28 L308,32 L312,32 L318,8 L322,60 L326,20 L330,32 L336,32
L376,32 L384,32 L388,28 L392,32 L396,32 L402,8 L406,60 L410,20 L414,32 L420,32
L460,32 L468,32 L472,28 L476,32 L480,32 L486,8 L490,60 L494,20 L498,32 L560,32"/>
</svg>
</div>
<div class="rpl-07__stats">
<div class="rpl-07__stat">
<div class="num">72</div>
<div class="lbl">BPM</div>
</div>
<div class="rpl-07__stat">
<div class="num">98%</div>
<div class="lbl">SpO₂</div>
</div>
<div class="rpl-07__stat">
<div class="num">120</div>
<div class="lbl">SBP</div>
</div>
<div class="rpl-07__stat">
<div class="num">80</div>
<div class="lbl">DBP</div>
</div>
</div>
<div class="rpl-07__live">
<div class="rpl-07__dot"></div>
Live monitoring · CSS animation only
</div>
</div><div class="rpl-07">
<div class="rpl-07__bg" id="rpl-07-bg"></div>
<div class="rpl-07__header">
<h1>Heartbeat Pulse Ripple Effect</h1>
<p>CSS keyframe animation with multi-wave pulse rings and ECG trace</p>
</div>
<div class="rpl-07__hero">
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__heart">❤️</div>
<div class="rpl-07__bpm"><b>72</b> BPM</div>
</div>
<div class="rpl-07__ecg">
<div class="rpl-07__ecg-label">ECG · Lead II</div>
<svg viewBox="0 0 560 64" preserveAspectRatio="none">
<path class="rpl-07__ecg-line"
d="M0,32 L40,32 L48,32 L52,28 L56,32 L60,32 L66,8 L70,60 L74,20 L78,32 L84,32
L124,32 L132,32 L136,28 L140,32 L144,32 L150,8 L154,60 L158,20 L162,32 L168,32
L208,32 L216,32 L220,28 L224,32 L228,32 L234,8 L238,60 L242,20 L246,32 L252,32
L292,32 L300,32 L304,28 L308,32 L312,32 L318,8 L322,60 L326,20 L330,32 L336,32
L376,32 L384,32 L388,28 L392,32 L396,32 L402,8 L406,60 L410,20 L414,32 L420,32
L460,32 L468,32 L472,28 L476,32 L480,32 L486,8 L490,60 L494,20 L498,32 L560,32"/>
</svg>
</div>
<div class="rpl-07__stats">
<div class="rpl-07__stat">
<div class="num">72</div>
<div class="lbl">BPM</div>
</div>
<div class="rpl-07__stat">
<div class="num">98%</div>
<div class="lbl">SpO₂</div>
</div>
<div class="rpl-07__stat">
<div class="num">120</div>
<div class="lbl">SBP</div>
</div>
<div class="rpl-07__stat">
<div class="num">80</div>
<div class="lbl">DBP</div>
</div>
</div>
<div class="rpl-07__live">
<div class="rpl-07__dot"></div>
Live monitoring · CSS animation only
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800&display=swap');
.rpl-07,
.rpl-07 *,
.rpl-07 *::before,
.rpl-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rpl-07 ::selection {
background: #fb2d5c;
color: #fff;
}
.rpl-07 {
font-family: 'Nunito', sans-serif;
background: linear-gradient(160deg, #0d0009 0%, #1a0010 40%, #0d000b 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 48px;
padding: 60px 24px;
color: #ffe8ee;
overflow: hidden;
position: relative;
}
/* subtle particles background */
.rpl-07__bg {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.rpl-07__bg-dot {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.35);
animation: rpl-07-float linear infinite;
}
@keyframes rpl-07-float {
0% {
transform: translateY(0) scale(1);
opacity: 0.6;
}
100% {
transform: translateY(-100vh) scale(0.2);
opacity: 0;
}
}
.rpl-07__header {
text-align: center;
z-index: 2;
}
.rpl-07__header h1 {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
letter-spacing: -0.02em;
color: #ffe8ee;
}
.rpl-07__header p {
margin-top: 8px;
color: rgba(255,232,238,0.45);
font-weight: 300;
font-size: 0.9rem;
}
/* ─── Hero heartbeat ─── */
.rpl-07__hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 220px;
height: 220px;
z-index: 2;
}
/* Pulse rings */
.rpl-07__pulse {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.15);
animation: rpl-07-pulse 1.5s ease-out infinite;
}
.rpl-07__pulse:nth-child(1) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__pulse:nth-child(2) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
.rpl-07__pulse:nth-child(3) {
width: 100%;
height: 100%;
animation-delay: 1.0s;
}
@keyframes rpl-07-pulse {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.7);
opacity: 0;
}
}
/* Ring borders */
.rpl-07__ring-border {
position: absolute;
border-radius: 50%;
border: 2px solid rgba(251,45,92,0.6);
animation: rpl-07-ring 1.5s ease-out infinite;
}
.rpl-07__ring-border:nth-child(4) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__ring-border:nth-child(5) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
@keyframes rpl-07-ring {
0% {
transform: scale(0.85);
opacity: 0.9;
}
100% {
transform: scale(1.65);
opacity: 0;
}
}
/* The heart itself */
.rpl-07__heart {
position: relative;
z-index: 3;
font-size: 72px;
line-height: 1;
animation: rpl-07-beat 1.5s ease-in-out infinite;
filter: drop-shadow(0 0 20px rgba(251,45,92,0.7)) drop-shadow(0 0 40px rgba(251,45,92,0.3));
}
@keyframes rpl-07-beat {
0%,
100% {
transform: scale(1);
}
14% {
transform: scale(1.18);
}
28% {
transform: scale(1);
}
42% {
transform: scale(1.12);
}
70% {
transform: scale(1);
}
}
/* BPM display */
.rpl-07__bpm {
position: absolute;
bottom: -36px;
font-size: 0.75rem;
color: rgba(255,232,238,0.5);
letter-spacing: 0.1em;
}
.rpl-07__bpm b {
color: #fb2d5c;
font-weight: 800;
font-size: 1.1rem;
}
/* ECG line SVG */
.rpl-07__ecg {
z-index: 2;
width: min(560px, 100%);
background: rgba(251,45,92,0.04);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 18px 20px;
overflow: hidden;
position: relative;
}
.rpl-07__ecg-label {
font-size: 0.65rem;
color: rgba(251,45,92,0.5);
letter-spacing: 0.2em;
text-transform: uppercase;
margin-bottom: 10px;
}
.rpl-07__ecg svg {
width: 100%;
height: 64px;
overflow: visible;
}
.rpl-07__ecg-line {
fill: none;
stroke: #fb2d5c;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
filter: drop-shadow(0 0 4px rgba(251,45,92,0.6));
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: rpl-07-draw 3s linear infinite;
}
@keyframes rpl-07-draw {
to {
stroke-dashoffset: 0;
}
}
/* Stats row */
.rpl-07__stats {
display: flex;
gap: 24px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-07__stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
background: rgba(251,45,92,0.06);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 16px 22px;
min-width: 100px;
}
.rpl-07__stat .num {
font-size: 1.5rem;
font-weight: 800;
color: #fb2d5c;
line-height: 1;
}
.rpl-07__stat .lbl {
font-size: 0.7rem;
color: rgba(255,232,238,0.4);
text-transform: uppercase;
letter-spacing: 0.1em;
}
/* Animated live indicator */
.rpl-07__live {
display: flex;
align-items: center;
gap: 8px;
z-index: 2;
font-size: 0.75rem;
color: rgba(255,232,238,0.4);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.rpl-07__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #fb2d5c;
box-shadow: 0 0 8px #fb2d5c;
animation: rpl-07-blink 1.5s steps(2) infinite;
}
@keyframes rpl-07-blink {
50% {
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.rpl-07__pulse,
.rpl-07__ring-border,
.rpl-07__heart,
.rpl-07__bg-dot,
.rpl-07__ecg-line,
.rpl-07__dot {
animation: none !important;
}
.rpl-07__pulse {
opacity: 0.2;
}
}@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800&display=swap');
.rpl-07,
.rpl-07 *,
.rpl-07 *::before,
.rpl-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rpl-07 ::selection {
background: #fb2d5c;
color: #fff;
}
.rpl-07 {
font-family: 'Nunito', sans-serif;
background: linear-gradient(160deg, #0d0009 0%, #1a0010 40%, #0d000b 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 48px;
padding: 60px 24px;
color: #ffe8ee;
overflow: hidden;
position: relative;
}
/* subtle particles background */
.rpl-07__bg {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.rpl-07__bg-dot {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.35);
animation: rpl-07-float linear infinite;
}
@keyframes rpl-07-float {
0% {
transform: translateY(0) scale(1);
opacity: 0.6;
}
100% {
transform: translateY(-100vh) scale(0.2);
opacity: 0;
}
}
.rpl-07__header {
text-align: center;
z-index: 2;
}
.rpl-07__header h1 {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
letter-spacing: -0.02em;
color: #ffe8ee;
}
.rpl-07__header p {
margin-top: 8px;
color: rgba(255,232,238,0.45);
font-weight: 300;
font-size: 0.9rem;
}
/* ─── Hero heartbeat ─── */
.rpl-07__hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 220px;
height: 220px;
z-index: 2;
}
/* Pulse rings */
.rpl-07__pulse {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.15);
animation: rpl-07-pulse 1.5s ease-out infinite;
}
.rpl-07__pulse:nth-child(1) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__pulse:nth-child(2) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
.rpl-07__pulse:nth-child(3) {
width: 100%;
height: 100%;
animation-delay: 1.0s;
}
@keyframes rpl-07-pulse {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.7);
opacity: 0;
}
}
/* Ring borders */
.rpl-07__ring-border {
position: absolute;
border-radius: 50%;
border: 2px solid rgba(251,45,92,0.6);
animation: rpl-07-ring 1.5s ease-out infinite;
}
.rpl-07__ring-border:nth-child(4) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__ring-border:nth-child(5) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
@keyframes rpl-07-ring {
0% {
transform: scale(0.85);
opacity: 0.9;
}
100% {
transform: scale(1.65);
opacity: 0;
}
}
/* The heart itself */
.rpl-07__heart {
position: relative;
z-index: 3;
font-size: 72px;
line-height: 1;
animation: rpl-07-beat 1.5s ease-in-out infinite;
filter: drop-shadow(0 0 20px rgba(251,45,92,0.7)) drop-shadow(0 0 40px rgba(251,45,92,0.3));
}
@keyframes rpl-07-beat {
0%,
100% {
transform: scale(1);
}
14% {
transform: scale(1.18);
}
28% {
transform: scale(1);
}
42% {
transform: scale(1.12);
}
70% {
transform: scale(1);
}
}
/* BPM display */
.rpl-07__bpm {
position: absolute;
bottom: -36px;
font-size: 0.75rem;
color: rgba(255,232,238,0.5);
letter-spacing: 0.1em;
}
.rpl-07__bpm b {
color: #fb2d5c;
font-weight: 800;
font-size: 1.1rem;
}
/* ECG line SVG */
.rpl-07__ecg {
z-index: 2;
width: min(560px, 100%);
background: rgba(251,45,92,0.04);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 18px 20px;
overflow: hidden;
position: relative;
}
.rpl-07__ecg-label {
font-size: 0.65rem;
color: rgba(251,45,92,0.5);
letter-spacing: 0.2em;
text-transform: uppercase;
margin-bottom: 10px;
}
.rpl-07__ecg svg {
width: 100%;
height: 64px;
overflow: visible;
}
.rpl-07__ecg-line {
fill: none;
stroke: #fb2d5c;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
filter: drop-shadow(0 0 4px rgba(251,45,92,0.6));
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: rpl-07-draw 3s linear infinite;
}
@keyframes rpl-07-draw {
to {
stroke-dashoffset: 0;
}
}
/* Stats row */
.rpl-07__stats {
display: flex;
gap: 24px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-07__stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
background: rgba(251,45,92,0.06);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 16px 22px;
min-width: 100px;
}
.rpl-07__stat .num {
font-size: 1.5rem;
font-weight: 800;
color: #fb2d5c;
line-height: 1;
}
.rpl-07__stat .lbl {
font-size: 0.7rem;
color: rgba(255,232,238,0.4);
text-transform: uppercase;
letter-spacing: 0.1em;
}
/* Animated live indicator */
.rpl-07__live {
display: flex;
align-items: center;
gap: 8px;
z-index: 2;
font-size: 0.75rem;
color: rgba(255,232,238,0.4);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.rpl-07__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #fb2d5c;
box-shadow: 0 0 8px #fb2d5c;
animation: rpl-07-blink 1.5s steps(2) infinite;
}
@keyframes rpl-07-blink {
50% {
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.rpl-07__pulse,
.rpl-07__ring-border,
.rpl-07__heart,
.rpl-07__bg-dot,
.rpl-07__ecg-line,
.rpl-07__dot {
animation: none !important;
}
.rpl-07__pulse {
opacity: 0.2;
}
}(function() {
const bg = document.getElementById('rpl-07-bg');
for (let i = 0; i < 20; i++) {
const d = document.createElement('div');
d.className = 'rpl-07__bg-dot';
const size = Math.random() * 4 + 1;
d.style.cssText = `
width:${size}px;height:${size}px;
left:${Math.random()*100}%;
top:${Math.random()*100}%;
animation-duration:${Math.random()*8+6}s;
animation-delay:${Math.random()*-8}s;
`;
bg.appendChild(d);
}
})();(function() {
const bg = document.getElementById('rpl-07-bg');
for (let i = 0; i < 20; i++) {
const d = document.createElement('div');
d.className = 'rpl-07__bg-dot';
const size = Math.random() * 4 + 1;
d.style.cssText = `
width:${size}px;height:${size}px;
left:${Math.random()*100}%;
top:${Math.random()*100}%;
animation-duration:${Math.random()*8+6}s;
animation-delay:${Math.random()*-8}s;
`;
bg.appendChild(d);
}
})();Here's a working CSS Ripple Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Heartbeat Pulse Ripple Effect
Source: https://codefronts.com/motion/css-ripple-designs/css-heartbeat-pulse-ripple-effect/
A cardiac monitor UI — a large animated heart icon with three concentric fill-pulse rings and two stroke rings, a looping SVG ECG trace with animated stroke-dashoffset, vital-signs stat tiles and a blinking LIVE indicator. All pulse timing matches a 72 BPM heartbeat rhythm. Nunito on deep maroon-black.
## HTML
```html
<div class="rpl-07">
<div class="rpl-07__bg" id="rpl-07-bg"></div>
<div class="rpl-07__header">
<h1>Heartbeat Pulse Ripple Effect</h1>
<p>CSS keyframe animation with multi-wave pulse rings and ECG trace</p>
</div>
<div class="rpl-07__hero">
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__heart">❤️</div>
<div class="rpl-07__bpm"><b>72</b> BPM</div>
</div>
<div class="rpl-07__ecg">
<div class="rpl-07__ecg-label">ECG · Lead II</div>
<svg viewBox="0 0 560 64" preserveAspectRatio="none">
<path class="rpl-07__ecg-line"
d="M0,32 L40,32 L48,32 L52,28 L56,32 L60,32 L66,8 L70,60 L74,20 L78,32 L84,32
L124,32 L132,32 L136,28 L140,32 L144,32 L150,8 L154,60 L158,20 L162,32 L168,32
L208,32 L216,32 L220,28 L224,32 L228,32 L234,8 L238,60 L242,20 L246,32 L252,32
L292,32 L300,32 L304,28 L308,32 L312,32 L318,8 L322,60 L326,20 L330,32 L336,32
L376,32 L384,32 L388,28 L392,32 L396,32 L402,8 L406,60 L410,20 L414,32 L420,32
L460,32 L468,32 L472,28 L476,32 L480,32 L486,8 L490,60 L494,20 L498,32 L560,32"/>
</svg>
</div>
<div class="rpl-07__stats">
<div class="rpl-07__stat">
<div class="num">72</div>
<div class="lbl">BPM</div>
</div>
<div class="rpl-07__stat">
<div class="num">98%</div>
<div class="lbl">SpO₂</div>
</div>
<div class="rpl-07__stat">
<div class="num">120</div>
<div class="lbl">SBP</div>
</div>
<div class="rpl-07__stat">
<div class="num">80</div>
<div class="lbl">DBP</div>
</div>
</div>
<div class="rpl-07__live">
<div class="rpl-07__dot"></div>
Live monitoring · CSS animation only
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800&display=swap');
.rpl-07,
.rpl-07 *,
.rpl-07 *::before,
.rpl-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rpl-07 ::selection {
background: #fb2d5c;
color: #fff;
}
.rpl-07 {
font-family: 'Nunito', sans-serif;
background: linear-gradient(160deg, #0d0009 0%, #1a0010 40%, #0d000b 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 48px;
padding: 60px 24px;
color: #ffe8ee;
overflow: hidden;
position: relative;
}
/* subtle particles background */
.rpl-07__bg {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.rpl-07__bg-dot {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.35);
animation: rpl-07-float linear infinite;
}
@keyframes rpl-07-float {
0% {
transform: translateY(0) scale(1);
opacity: 0.6;
}
100% {
transform: translateY(-100vh) scale(0.2);
opacity: 0;
}
}
.rpl-07__header {
text-align: center;
z-index: 2;
}
.rpl-07__header h1 {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
letter-spacing: -0.02em;
color: #ffe8ee;
}
.rpl-07__header p {
margin-top: 8px;
color: rgba(255,232,238,0.45);
font-weight: 300;
font-size: 0.9rem;
}
/* ─── Hero heartbeat ─── */
.rpl-07__hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 220px;
height: 220px;
z-index: 2;
}
/* Pulse rings */
.rpl-07__pulse {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.15);
animation: rpl-07-pulse 1.5s ease-out infinite;
}
.rpl-07__pulse:nth-child(1) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__pulse:nth-child(2) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
.rpl-07__pulse:nth-child(3) {
width: 100%;
height: 100%;
animation-delay: 1.0s;
}
@keyframes rpl-07-pulse {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.7);
opacity: 0;
}
}
/* Ring borders */
.rpl-07__ring-border {
position: absolute;
border-radius: 50%;
border: 2px solid rgba(251,45,92,0.6);
animation: rpl-07-ring 1.5s ease-out infinite;
}
.rpl-07__ring-border:nth-child(4) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__ring-border:nth-child(5) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
@keyframes rpl-07-ring {
0% {
transform: scale(0.85);
opacity: 0.9;
}
100% {
transform: scale(1.65);
opacity: 0;
}
}
/* The heart itself */
.rpl-07__heart {
position: relative;
z-index: 3;
font-size: 72px;
line-height: 1;
animation: rpl-07-beat 1.5s ease-in-out infinite;
filter: drop-shadow(0 0 20px rgba(251,45,92,0.7)) drop-shadow(0 0 40px rgba(251,45,92,0.3));
}
@keyframes rpl-07-beat {
0%,
100% {
transform: scale(1);
}
14% {
transform: scale(1.18);
}
28% {
transform: scale(1);
}
42% {
transform: scale(1.12);
}
70% {
transform: scale(1);
}
}
/* BPM display */
.rpl-07__bpm {
position: absolute;
bottom: -36px;
font-size: 0.75rem;
color: rgba(255,232,238,0.5);
letter-spacing: 0.1em;
}
.rpl-07__bpm b {
color: #fb2d5c;
font-weight: 800;
font-size: 1.1rem;
}
/* ECG line SVG */
.rpl-07__ecg {
z-index: 2;
width: min(560px, 100%);
background: rgba(251,45,92,0.04);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 18px 20px;
overflow: hidden;
position: relative;
}
.rpl-07__ecg-label {
font-size: 0.65rem;
color: rgba(251,45,92,0.5);
letter-spacing: 0.2em;
text-transform: uppercase;
margin-bottom: 10px;
}
.rpl-07__ecg svg {
width: 100%;
height: 64px;
overflow: visible;
}
.rpl-07__ecg-line {
fill: none;
stroke: #fb2d5c;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
filter: drop-shadow(0 0 4px rgba(251,45,92,0.6));
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: rpl-07-draw 3s linear infinite;
}
@keyframes rpl-07-draw {
to {
stroke-dashoffset: 0;
}
}
/* Stats row */
.rpl-07__stats {
display: flex;
gap: 24px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-07__stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
background: rgba(251,45,92,0.06);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 16px 22px;
min-width: 100px;
}
.rpl-07__stat .num {
font-size: 1.5rem;
font-weight: 800;
color: #fb2d5c;
line-height: 1;
}
.rpl-07__stat .lbl {
font-size: 0.7rem;
color: rgba(255,232,238,0.4);
text-transform: uppercase;
letter-spacing: 0.1em;
}
/* Animated live indicator */
.rpl-07__live {
display: flex;
align-items: center;
gap: 8px;
z-index: 2;
font-size: 0.75rem;
color: rgba(255,232,238,0.4);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.rpl-07__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #fb2d5c;
box-shadow: 0 0 8px #fb2d5c;
animation: rpl-07-blink 1.5s steps(2) infinite;
}
@keyframes rpl-07-blink {
50% {
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.rpl-07__pulse,
.rpl-07__ring-border,
.rpl-07__heart,
.rpl-07__bg-dot,
.rpl-07__ecg-line,
.rpl-07__dot {
animation: none !important;
}
.rpl-07__pulse {
opacity: 0.2;
}
}
```
## JavaScript
```js
(function() {
const bg = document.getElementById('rpl-07-bg');
for (let i = 0; i < 20; i++) {
const d = document.createElement('div');
d.className = 'rpl-07__bg-dot';
const size = Math.random() * 4 + 1;
d.style.cssText = `
width:${size}px;height:${size}px;
left:${Math.random()*100}%;
top:${Math.random()*100}%;
animation-duration:${Math.random()*8+6}s;
animation-delay:${Math.random()*-8}s;
`;
bg.appendChild(d);
}
})();
```Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Ripple Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Heartbeat Pulse Ripple Effect
Source: https://codefronts.com/motion/css-ripple-designs/css-heartbeat-pulse-ripple-effect/
A cardiac monitor UI — a large animated heart icon with three concentric fill-pulse rings and two stroke rings, a looping SVG ECG trace with animated stroke-dashoffset, vital-signs stat tiles and a blinking LIVE indicator. All pulse timing matches a 72 BPM heartbeat rhythm. Nunito on deep maroon-black.
## HTML
```html
<div class="rpl-07">
<div class="rpl-07__bg" id="rpl-07-bg"></div>
<div class="rpl-07__header">
<h1>Heartbeat Pulse Ripple Effect</h1>
<p>CSS keyframe animation with multi-wave pulse rings and ECG trace</p>
</div>
<div class="rpl-07__hero">
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__pulse"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__ring-border"></div>
<div class="rpl-07__heart">❤️</div>
<div class="rpl-07__bpm"><b>72</b> BPM</div>
</div>
<div class="rpl-07__ecg">
<div class="rpl-07__ecg-label">ECG · Lead II</div>
<svg viewBox="0 0 560 64" preserveAspectRatio="none">
<path class="rpl-07__ecg-line"
d="M0,32 L40,32 L48,32 L52,28 L56,32 L60,32 L66,8 L70,60 L74,20 L78,32 L84,32
L124,32 L132,32 L136,28 L140,32 L144,32 L150,8 L154,60 L158,20 L162,32 L168,32
L208,32 L216,32 L220,28 L224,32 L228,32 L234,8 L238,60 L242,20 L246,32 L252,32
L292,32 L300,32 L304,28 L308,32 L312,32 L318,8 L322,60 L326,20 L330,32 L336,32
L376,32 L384,32 L388,28 L392,32 L396,32 L402,8 L406,60 L410,20 L414,32 L420,32
L460,32 L468,32 L472,28 L476,32 L480,32 L486,8 L490,60 L494,20 L498,32 L560,32"/>
</svg>
</div>
<div class="rpl-07__stats">
<div class="rpl-07__stat">
<div class="num">72</div>
<div class="lbl">BPM</div>
</div>
<div class="rpl-07__stat">
<div class="num">98%</div>
<div class="lbl">SpO₂</div>
</div>
<div class="rpl-07__stat">
<div class="num">120</div>
<div class="lbl">SBP</div>
</div>
<div class="rpl-07__stat">
<div class="num">80</div>
<div class="lbl">DBP</div>
</div>
</div>
<div class="rpl-07__live">
<div class="rpl-07__dot"></div>
Live monitoring · CSS animation only
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800&display=swap');
.rpl-07,
.rpl-07 *,
.rpl-07 *::before,
.rpl-07 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rpl-07 ::selection {
background: #fb2d5c;
color: #fff;
}
.rpl-07 {
font-family: 'Nunito', sans-serif;
background: linear-gradient(160deg, #0d0009 0%, #1a0010 40%, #0d000b 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 48px;
padding: 60px 24px;
color: #ffe8ee;
overflow: hidden;
position: relative;
}
/* subtle particles background */
.rpl-07__bg {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.rpl-07__bg-dot {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.35);
animation: rpl-07-float linear infinite;
}
@keyframes rpl-07-float {
0% {
transform: translateY(0) scale(1);
opacity: 0.6;
}
100% {
transform: translateY(-100vh) scale(0.2);
opacity: 0;
}
}
.rpl-07__header {
text-align: center;
z-index: 2;
}
.rpl-07__header h1 {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
letter-spacing: -0.02em;
color: #ffe8ee;
}
.rpl-07__header p {
margin-top: 8px;
color: rgba(255,232,238,0.45);
font-weight: 300;
font-size: 0.9rem;
}
/* ─── Hero heartbeat ─── */
.rpl-07__hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 220px;
height: 220px;
z-index: 2;
}
/* Pulse rings */
.rpl-07__pulse {
position: absolute;
border-radius: 50%;
background: rgba(251,45,92,0.15);
animation: rpl-07-pulse 1.5s ease-out infinite;
}
.rpl-07__pulse:nth-child(1) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__pulse:nth-child(2) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
.rpl-07__pulse:nth-child(3) {
width: 100%;
height: 100%;
animation-delay: 1.0s;
}
@keyframes rpl-07-pulse {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.7);
opacity: 0;
}
}
/* Ring borders */
.rpl-07__ring-border {
position: absolute;
border-radius: 50%;
border: 2px solid rgba(251,45,92,0.6);
animation: rpl-07-ring 1.5s ease-out infinite;
}
.rpl-07__ring-border:nth-child(4) {
width: 100%;
height: 100%;
animation-delay: 0s;
}
.rpl-07__ring-border:nth-child(5) {
width: 100%;
height: 100%;
animation-delay: 0.5s;
}
@keyframes rpl-07-ring {
0% {
transform: scale(0.85);
opacity: 0.9;
}
100% {
transform: scale(1.65);
opacity: 0;
}
}
/* The heart itself */
.rpl-07__heart {
position: relative;
z-index: 3;
font-size: 72px;
line-height: 1;
animation: rpl-07-beat 1.5s ease-in-out infinite;
filter: drop-shadow(0 0 20px rgba(251,45,92,0.7)) drop-shadow(0 0 40px rgba(251,45,92,0.3));
}
@keyframes rpl-07-beat {
0%,
100% {
transform: scale(1);
}
14% {
transform: scale(1.18);
}
28% {
transform: scale(1);
}
42% {
transform: scale(1.12);
}
70% {
transform: scale(1);
}
}
/* BPM display */
.rpl-07__bpm {
position: absolute;
bottom: -36px;
font-size: 0.75rem;
color: rgba(255,232,238,0.5);
letter-spacing: 0.1em;
}
.rpl-07__bpm b {
color: #fb2d5c;
font-weight: 800;
font-size: 1.1rem;
}
/* ECG line SVG */
.rpl-07__ecg {
z-index: 2;
width: min(560px, 100%);
background: rgba(251,45,92,0.04);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 18px 20px;
overflow: hidden;
position: relative;
}
.rpl-07__ecg-label {
font-size: 0.65rem;
color: rgba(251,45,92,0.5);
letter-spacing: 0.2em;
text-transform: uppercase;
margin-bottom: 10px;
}
.rpl-07__ecg svg {
width: 100%;
height: 64px;
overflow: visible;
}
.rpl-07__ecg-line {
fill: none;
stroke: #fb2d5c;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
filter: drop-shadow(0 0 4px rgba(251,45,92,0.6));
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: rpl-07-draw 3s linear infinite;
}
@keyframes rpl-07-draw {
to {
stroke-dashoffset: 0;
}
}
/* Stats row */
.rpl-07__stats {
display: flex;
gap: 24px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-07__stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
background: rgba(251,45,92,0.06);
border: 1px solid rgba(251,45,92,0.15);
border-radius: 12px;
padding: 16px 22px;
min-width: 100px;
}
.rpl-07__stat .num {
font-size: 1.5rem;
font-weight: 800;
color: #fb2d5c;
line-height: 1;
}
.rpl-07__stat .lbl {
font-size: 0.7rem;
color: rgba(255,232,238,0.4);
text-transform: uppercase;
letter-spacing: 0.1em;
}
/* Animated live indicator */
.rpl-07__live {
display: flex;
align-items: center;
gap: 8px;
z-index: 2;
font-size: 0.75rem;
color: rgba(255,232,238,0.4);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.rpl-07__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #fb2d5c;
box-shadow: 0 0 8px #fb2d5c;
animation: rpl-07-blink 1.5s steps(2) infinite;
}
@keyframes rpl-07-blink {
50% {
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.rpl-07__pulse,
.rpl-07__ring-border,
.rpl-07__heart,
.rpl-07__bg-dot,
.rpl-07__ecg-line,
.rpl-07__dot {
animation: none !important;
}
.rpl-07__pulse {
opacity: 0.2;
}
}
```
## JavaScript
```js
(function() {
const bg = document.getElementById('rpl-07-bg');
for (let i = 0; i < 20; i++) {
const d = document.createElement('div');
d.className = 'rpl-07__bg-dot';
const size = Math.random() * 4 + 1;
d.style.cssText = `
width:${size}px;height:${size}px;
left:${Math.random()*100}%;
top:${Math.random()*100}%;
animation-duration:${Math.random()*8+6}s;
animation-delay:${Math.random()*-8}s;
`;
bg.appendChild(d);
}
})();
```