Click Ripple Cursor
A click ripple effect that creates an expanding animated circle exactly where the user clicks inside the preview area.
<div class="click-ripple-area">
<div class="click-ripple-content">
Click anywhere inside this area
</div>
</div>
.click-ripple-area{
position:relative;
width:100%;
min-height:220px;
display:flex;
align-items:center;
justify-content:center;
overflow:hidden;
cursor:pointer;
background:
radial-gradient(
circle at center,
rgba(34,211,238,.04),
transparent 55%
),
#070d19;
}
.click-ripple-content{
position:relative;
z-index:2;
color:#c7d2e5;
font-size:16px;
font-weight:600;
text-align:center;
pointer-events:none;
}
.click-ripple{
position:absolute;
z-index:1;
width:20px;
height:20px;
border:2px solid #22d3ee;
border-radius:50%;
background:rgba(34,211,238,.08);
pointer-events:none;
transform:
translate(-50%, -50%)
scale(0);
box-shadow:
0 0 20px rgba(34,211,238,.25);
animation:
clickRipple .7s ease-out forwards;
}
@keyframes clickRipple{
0%{
opacity:1;
transform:
translate(-50%, -50%)
scale(0);
}
60%{
opacity:.6;
}
100%{
opacity:0;
transform:
translate(-50%, -50%)
scale(6);
}
}
const area =
document.querySelector('.click-ripple-area');
if (area) {
area.addEventListener(
'click',
function(event) {
const rect =
area.getBoundingClientRect();
const ripple =
document.createElement('span');
ripple.className =
'click-ripple';
ripple.style.left =
event.clientX -
rect.left +
'px';
ripple.style.top =
event.clientY -
rect.top +
'px';
area.appendChild(ripple);
setTimeout(
function() {
ripple.remove();
},
700
);
}
);
}
How This Component Works
This click ripple cursor effect creates a small expanding circle exactly at the point where the user clicks — similar to the ripple you’d see when a drop hits water. The HTML is minimal: a single container (click-ripple-area) with a text label inside it telling users where to click.
The real logic sits in the JavaScript. It listens for a click event on the container, and every time a click happens, it calculates the exact X and Y coordinates of the click relative to the container using getBoundingClientRect(). It then dynamically creates a new span element with the class click-ripple, positions it at those exact coordinates, and appends it into the container. After 700 milliseconds, that same ripple element is automatically removed from the page using setTimeout, so old ripples don’t pile up in the background.
The visual animation itself is handled entirely by CSS through a @keyframes rule called clickRipple. When a ripple element is created, it starts as a tiny circle at scale(0) with full opacity, then grows outward to scale(6) while fading to zero opacity over 0.7 seconds. Because the JavaScript generates a brand-new ripple element on every single click, multiple clicks in quick succession will show multiple overlapping ripples animating independently.
Customization Tips
This effect is easy to adjust through just a few CSS values:
- Change the ripple color — update the
borderandbox-shadowcolors in.click-ripple(currently cyan) to match your site’s theme. - Adjust how far it expands — change the
scale(6)value inside the100%keyframe step; a smaller number keeps the ripple more compact, a larger one makes it spread further. - Control animation speed — the
.7sduration on theclickRippleanimation can be shortened for a quicker pop or lengthened for a slower, more dramatic spread. - Change the starting size — the
widthandheighton.click-ripple(currently 20px) set how big the ripple is before it starts expanding.
Where to Use This
Since this effect responds directly to clicks rather than hover or movement, it works best for confirming user actions visually:
- Buttons and call-to-action areas, where a ripple gives users instant visual feedback that their click registered.
- Interactive cards or tiles, especially in dashboards or portfolios, to make clicking feel more responsive.
- Games or playful landing pages, where click feedback adds a bit of personality to every interaction.
It’s less suited for form fields or text-heavy areas, since the ripple is a purely decorative confirmation and isn’t tied to any functional click action like form submission.
If you’re looking for a hover-based effect instead of a click-based one, check out our Cursor Ring Hover Effect component, which reacts to mouse movement rather than clicks.
Frequently Asked Questions
Does the ripple appear only once, or can I click multiple times quickly?
You can click as many times as you want, and each click generates its own independent ripple. Since JavaScript creates a new element for every click and removes it automatically after the animation ends, overlapping ripples from rapid clicking work fine without any conflicts.
Will old ripples stay on the page and affect performance?
No. Every ripple element is automatically deleted from the DOM 700 milliseconds after it’s created, which matches the exact length of its CSS animation. This means there’s no buildup of leftover elements, even with frequent clicking.
Can I trigger this ripple effect on a button instead of a full container?
Yes — since the effect is triggered by a click event listener using event.target.closest(), you can apply the click-ripple-area class directly to a button or any clickable element instead of a large container, and the ripple will still calculate its position correctly.
