12 CSS Ripple Effects 01 / 12
CSS Water Ripple Click Effect
An interactive water-surface pond you click to create realistic multi-ring ripples — four concentric CSS rings (box-shadow glow, fade-out scale) spawn at the exact cursor coordinate via JS, plus a radial-gradient caustic shimmer overlay and animated floating bubble particles.
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-01">
<div class="rpl-01__header">
<h1>Water Ripple Click Effect</h1>
<p>Click anywhere on the surface to create realistic water ripples</p>
</div>
<div class="rpl-01__pond" id="rpl-01-pond">
<div class="rpl-01__label">click the surface</div>
</div>
<div class="rpl-01__info">
<div class="rpl-01__stat">
<b id="rpl-01-count">0</b>
<span>Drops</span>
</div>
<div class="rpl-01__stat">
<b id="rpl-01-rings">0</b>
<span>Active Rings</span>
</div>
</div>
</div> <div class="rpl-01">
<div class="rpl-01__header">
<h1>Water Ripple Click Effect</h1>
<p>Click anywhere on the surface to create realistic water ripples</p>
</div>
<div class="rpl-01__pond" id="rpl-01-pond">
<div class="rpl-01__label">click the surface</div>
</div>
<div class="rpl-01__info">
<div class="rpl-01__stat">
<b id="rpl-01-count">0</b>
<span>Drops</span>
</div>
<div class="rpl-01__stat">
<b id="rpl-01-rings">0</b>
<span>Active Rings</span>
</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap');
.rpl-01, .rpl-01 *, .rpl-01 *::before, .rpl-01 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.rpl-01 ::selection { background: #00d4ff; color: #001a2e; }
.rpl-01 {
--deep: #001a2e;
--mid: #003a5c;
--water: #00a8cc;
--foam: #00d4ff;
--glint: #7ef7ff;
--text: #e0f7ff;
font-family: 'Outfit', sans-serif;
background: radial-gradient(ellipse at 50% 0%, #003a5c, #001015 70%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px 20px;
color: var(--text);
overflow: hidden;
position: relative;
}
/* Animated depth lines */
.rpl-01::before {
content: '';
position: absolute;
inset: 0;
background:
repeating-linear-gradient(0deg, transparent 0px, transparent 48px, rgba(0,168,204,0.06) 48px, rgba(0,168,204,0.06) 50px);
pointer-events: none;
}
.rpl-01__header {
text-align: center;
z-index: 2;
}
.rpl-01__header h1 {
font-size: clamp(1.8rem, 5vw, 3rem);
font-weight: 700;
letter-spacing: -0.02em;
background: linear-gradient(135deg, var(--glint), var(--foam), var(--water));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.rpl-01__header p {
margin-top: 8px;
font-size: 1rem;
color: rgba(224,247,255,0.55);
font-weight: 300;
}
/* The water surface */
.rpl-01__pond {
width: min(700px, 100%);
height: 400px;
position: relative;
border-radius: 20px;
overflow: hidden;
cursor: crosshair;
border: 1px solid rgba(0,212,255,0.2);
box-shadow: 0 0 60px rgba(0,168,204,0.25), inset 0 0 80px rgba(0,20,40,0.6);
background:
radial-gradient(ellipse at 50% 0%, rgba(0,168,204,0.18), transparent 60%),
linear-gradient(180deg, #001f38 0%, #000e1a 100%);
z-index: 2;
}
/* Caustic shimmer overlay */
.rpl-01__pond::before {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 200% 80% at 50% 100%, rgba(0,168,204,0.12), transparent),
repeating-linear-gradient(60deg, transparent 0px, transparent 20px, rgba(0,212,255,0.03) 20px, rgba(0,212,255,0.03) 21px),
repeating-linear-gradient(-60deg, transparent 0px, transparent 20px, rgba(0,212,255,0.03) 20px, rgba(0,212,255,0.03) 21px);
animation: rpl-01-caustic 8s linear infinite;
pointer-events: none;
z-index: 1;
}
@keyframes rpl-01-caustic { to { background-position: 0 40px, 30px 0, -30px 0; } }
.rpl-01__pond::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(180deg, transparent 60%, rgba(0,10,20,0.5) 100%);
pointer-events: none;
z-index: 3;
}
/* A ripple ring spawned by JS */
.rpl-01__ripple {
position: absolute;
border-radius: 50%;
transform: translate(-50%, -50%) scale(0);
pointer-events: none;
z-index: 2;
animation: rpl-01-wave 2.4s cubic-bezier(0.2, 0.6, 0.4, 1) forwards;
}
@keyframes rpl-01-wave {
0% { transform: translate(-50%,-50%) scale(0); opacity: 1; }
100% { transform: translate(-50%,-50%) scale(1); opacity: 0; }
}
/* Three concentric ring sizes */
.rpl-01__ripple--a {
width: 60px; height: 60px;
border: 2px solid rgba(0,212,255,0.9);
box-shadow: 0 0 12px rgba(0,212,255,0.5), inset 0 0 12px rgba(0,212,255,0.1);
}
.rpl-01__ripple--b {
width: 130px; height: 130px;
border: 1.5px solid rgba(0,168,204,0.65);
box-shadow: 0 0 20px rgba(0,168,204,0.3);
animation-delay: 0.12s;
}
.rpl-01__ripple--c {
width: 220px; height: 220px;
border: 1px solid rgba(0,120,160,0.4);
animation-delay: 0.26s;
}
.rpl-01__ripple--d {
width: 340px; height: 340px;
border: 0.5px solid rgba(0,90,120,0.25);
animation-delay: 0.44s;
}
/* Center drop dot */
.rpl-01__drop {
position: absolute;
width: 8px; height: 8px;
border-radius: 50%;
background: radial-gradient(circle at 35% 30%, #7ef7ff, #00d4ff);
transform: translate(-50%, -50%) scale(0);
pointer-events: none;
z-index: 4;
animation: rpl-01-drop 0.4s cubic-bezier(0.2, 0.9, 0.4, 1) forwards;
box-shadow: 0 0 14px #00d4ff;
}
@keyframes rpl-01-drop {
0% { transform: translate(-50%,-50%) scale(0); opacity: 1; }
60% { transform: translate(-50%,-50%) scale(1.4); opacity: 1; }
100% { transform: translate(-50%,-50%) scale(0.6); opacity: 0; }
}
.rpl-01__label {
position: absolute;
bottom: 18px;
left: 50%;
transform: translateX(-50%);
font-size: 0.75rem;
color: rgba(0,212,255,0.4);
letter-spacing: 0.2em;
text-transform: uppercase;
z-index: 4;
pointer-events: none;
animation: rpl-01-pulse 2s ease-in-out infinite;
}
@keyframes rpl-01-pulse { 50% { opacity: 0.2; } }
/* Ambient floating particles */
.rpl-01__particle {
position: absolute;
border-radius: 50%;
background: rgba(0,212,255,0.6);
pointer-events: none;
z-index: 1;
animation: rpl-01-float linear infinite;
}
@keyframes rpl-01-float {
0% { transform: translateY(0) scale(1); opacity: 0.6; }
50% { opacity: 0.2; }
100% { transform: translateY(-380px) scale(0.3); opacity: 0; }
}
.rpl-01__info {
display: flex;
gap: 32px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-01__stat {
text-align: center;
}
.rpl-01__stat b {
display: block;
font-size: 1.8rem;
font-weight: 700;
color: var(--foam);
}
.rpl-01__stat span {
font-size: 0.75rem;
color: rgba(224,247,255,0.4);
letter-spacing: 0.15em;
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.rpl-01__pond::before, .rpl-01__label, .rpl-01__particle { animation: none !important; }
.rpl-01__ripple, .rpl-01__drop { animation-duration: 0.01ms !important; }
} @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap');
.rpl-01, .rpl-01 *, .rpl-01 *::before, .rpl-01 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.rpl-01 ::selection { background: #00d4ff; color: #001a2e; }
.rpl-01 {
--deep: #001a2e;
--mid: #003a5c;
--water: #00a8cc;
--foam: #00d4ff;
--glint: #7ef7ff;
--text: #e0f7ff;
font-family: 'Outfit', sans-serif;
background: radial-gradient(ellipse at 50% 0%, #003a5c, #001015 70%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px 20px;
color: var(--text);
overflow: hidden;
position: relative;
}
/* Animated depth lines */
.rpl-01::before {
content: '';
position: absolute;
inset: 0;
background:
repeating-linear-gradient(0deg, transparent 0px, transparent 48px, rgba(0,168,204,0.06) 48px, rgba(0,168,204,0.06) 50px);
pointer-events: none;
}
.rpl-01__header {
text-align: center;
z-index: 2;
}
.rpl-01__header h1 {
font-size: clamp(1.8rem, 5vw, 3rem);
font-weight: 700;
letter-spacing: -0.02em;
background: linear-gradient(135deg, var(--glint), var(--foam), var(--water));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.rpl-01__header p {
margin-top: 8px;
font-size: 1rem;
color: rgba(224,247,255,0.55);
font-weight: 300;
}
/* The water surface */
.rpl-01__pond {
width: min(700px, 100%);
height: 400px;
position: relative;
border-radius: 20px;
overflow: hidden;
cursor: crosshair;
border: 1px solid rgba(0,212,255,0.2);
box-shadow: 0 0 60px rgba(0,168,204,0.25), inset 0 0 80px rgba(0,20,40,0.6);
background:
radial-gradient(ellipse at 50% 0%, rgba(0,168,204,0.18), transparent 60%),
linear-gradient(180deg, #001f38 0%, #000e1a 100%);
z-index: 2;
}
/* Caustic shimmer overlay */
.rpl-01__pond::before {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 200% 80% at 50% 100%, rgba(0,168,204,0.12), transparent),
repeating-linear-gradient(60deg, transparent 0px, transparent 20px, rgba(0,212,255,0.03) 20px, rgba(0,212,255,0.03) 21px),
repeating-linear-gradient(-60deg, transparent 0px, transparent 20px, rgba(0,212,255,0.03) 20px, rgba(0,212,255,0.03) 21px);
animation: rpl-01-caustic 8s linear infinite;
pointer-events: none;
z-index: 1;
}
@keyframes rpl-01-caustic { to { background-position: 0 40px, 30px 0, -30px 0; } }
.rpl-01__pond::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(180deg, transparent 60%, rgba(0,10,20,0.5) 100%);
pointer-events: none;
z-index: 3;
}
/* A ripple ring spawned by JS */
.rpl-01__ripple {
position: absolute;
border-radius: 50%;
transform: translate(-50%, -50%) scale(0);
pointer-events: none;
z-index: 2;
animation: rpl-01-wave 2.4s cubic-bezier(0.2, 0.6, 0.4, 1) forwards;
}
@keyframes rpl-01-wave {
0% { transform: translate(-50%,-50%) scale(0); opacity: 1; }
100% { transform: translate(-50%,-50%) scale(1); opacity: 0; }
}
/* Three concentric ring sizes */
.rpl-01__ripple--a {
width: 60px; height: 60px;
border: 2px solid rgba(0,212,255,0.9);
box-shadow: 0 0 12px rgba(0,212,255,0.5), inset 0 0 12px rgba(0,212,255,0.1);
}
.rpl-01__ripple--b {
width: 130px; height: 130px;
border: 1.5px solid rgba(0,168,204,0.65);
box-shadow: 0 0 20px rgba(0,168,204,0.3);
animation-delay: 0.12s;
}
.rpl-01__ripple--c {
width: 220px; height: 220px;
border: 1px solid rgba(0,120,160,0.4);
animation-delay: 0.26s;
}
.rpl-01__ripple--d {
width: 340px; height: 340px;
border: 0.5px solid rgba(0,90,120,0.25);
animation-delay: 0.44s;
}
/* Center drop dot */
.rpl-01__drop {
position: absolute;
width: 8px; height: 8px;
border-radius: 50%;
background: radial-gradient(circle at 35% 30%, #7ef7ff, #00d4ff);
transform: translate(-50%, -50%) scale(0);
pointer-events: none;
z-index: 4;
animation: rpl-01-drop 0.4s cubic-bezier(0.2, 0.9, 0.4, 1) forwards;
box-shadow: 0 0 14px #00d4ff;
}
@keyframes rpl-01-drop {
0% { transform: translate(-50%,-50%) scale(0); opacity: 1; }
60% { transform: translate(-50%,-50%) scale(1.4); opacity: 1; }
100% { transform: translate(-50%,-50%) scale(0.6); opacity: 0; }
}
.rpl-01__label {
position: absolute;
bottom: 18px;
left: 50%;
transform: translateX(-50%);
font-size: 0.75rem;
color: rgba(0,212,255,0.4);
letter-spacing: 0.2em;
text-transform: uppercase;
z-index: 4;
pointer-events: none;
animation: rpl-01-pulse 2s ease-in-out infinite;
}
@keyframes rpl-01-pulse { 50% { opacity: 0.2; } }
/* Ambient floating particles */
.rpl-01__particle {
position: absolute;
border-radius: 50%;
background: rgba(0,212,255,0.6);
pointer-events: none;
z-index: 1;
animation: rpl-01-float linear infinite;
}
@keyframes rpl-01-float {
0% { transform: translateY(0) scale(1); opacity: 0.6; }
50% { opacity: 0.2; }
100% { transform: translateY(-380px) scale(0.3); opacity: 0; }
}
.rpl-01__info {
display: flex;
gap: 32px;
z-index: 2;
flex-wrap: wrap;
justify-content: center;
}
.rpl-01__stat {
text-align: center;
}
.rpl-01__stat b {
display: block;
font-size: 1.8rem;
font-weight: 700;
color: var(--foam);
}
.rpl-01__stat span {
font-size: 0.75rem;
color: rgba(224,247,255,0.4);
letter-spacing: 0.15em;
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.rpl-01__pond::before, .rpl-01__label, .rpl-01__particle { animation: none !important; }
.rpl-01__ripple, .rpl-01__drop { animation-duration: 0.01ms !important; }
}(() => {
const pond = document.getElementById('rpl-01-pond');
const countEl = document.getElementById('rpl-01-count');
const ringsEl = document.getElementById('rpl-01-rings');
let dropCount = 0;
let activeRings = 0;
// Spawn ambient particles
for (let i = 0; i < 12; i++) {
const p = document.createElement('div');
p.className = 'rpl-01__particle';
const size = Math.random() * 4 + 1;
p.style.cssText = `
width:${size}px; height:${size}px;
left:${Math.random()*100}%;
bottom:${Math.random()*100}%;
opacity:${Math.random()*0.6+0.1};
animation-duration:${Math.random()*6+4}s;
animation-delay:${Math.random()*-6}s;
`;
pond.appendChild(p);
}
pond.addEventListener('click', (e) => {
const rect = pond.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
dropCount++;
countEl.textContent = dropCount;
// spawn drop dot
const drop = document.createElement('div');
drop.className = 'rpl-01__drop';
drop.style.left = x + 'px';
drop.style.top = y + 'px';
pond.appendChild(drop);
// spawn 4 concentric rings
['a','b','c','d'].forEach((t, i) => {
const r = document.createElement('div');
r.className = `rpl-01__ripple rpl-01__ripple--${t}`;
r.style.left = x + 'px';
r.style.top = y + 'px';
pond.appendChild(r);
activeRings++;
ringsEl.textContent = activeRings;
r.addEventListener('animationend', () => {
r.remove();
activeRings = Math.max(0, activeRings - 1);
ringsEl.textContent = activeRings;
}, { once: true });
});
drop.addEventListener('animationend', () => drop.remove(), { once: true });
});
})(); (() => {
const pond = document.getElementById('rpl-01-pond');
const countEl = document.getElementById('rpl-01-count');
const ringsEl = document.getElementById('rpl-01-rings');
let dropCount = 0;
let activeRings = 0;
// Spawn ambient particles
for (let i = 0; i < 12; i++) {
const p = document.createElement('div');
p.className = 'rpl-01__particle';
const size = Math.random() * 4 + 1;
p.style.cssText = `
width:${size}px; height:${size}px;
left:${Math.random()*100}%;
bottom:${Math.random()*100}%;
opacity:${Math.random()*0.6+0.1};
animation-duration:${Math.random()*6+4}s;
animation-delay:${Math.random()*-6}s;
`;
pond.appendChild(p);
}
pond.addEventListener('click', (e) => {
const rect = pond.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
dropCount++;
countEl.textContent = dropCount;
// spawn drop dot
const drop = document.createElement('div');
drop.className = 'rpl-01__drop';
drop.style.left = x + 'px';
drop.style.top = y + 'px';
pond.appendChild(drop);
// spawn 4 concentric rings
['a','b','c','d'].forEach((t, i) => {
const r = document.createElement('div');
r.className = `rpl-01__ripple rpl-01__ripple--${t}`;
r.style.left = x + 'px';
r.style.top = y + 'px';
pond.appendChild(r);
activeRings++;
ringsEl.textContent = activeRings;
r.addEventListener('animationend', () => {
r.remove();
activeRings = Math.max(0, activeRings - 1);
ringsEl.textContent = activeRings;
}, { once: true });
});
drop.addEventListener('animationend', () => drop.remove(), { once: true });
});
})();More from 12 CSS Ripple Effects
CSS Ripple Button Click AnimationCSS Pond Ripple Background AnimationCSS Heartbeat Pulse Ripple EffectCSS Ripple Login Form UICSS Aurora Borealis Ripple BackgroundCSS Neon Glow Ripple EffectCSS Ripple Loading SpinnerCSS Sonar Ping Ripple AnimationCSS Ripple Card Hover EffectCSS Sound Wave Ripple VisualizerCSS Liquid Drop Ripple Animation
View the full collection →