DEV Community

Leonardo Schmitt
Leonardo Schmitt

Posted on • Updated on

How to make a mouse ripple click effect with CSS, JS and HTML in 2 steps馃柋锔忊毆


So today you will build this cool ripple effect of the mouse cursor, using HTML5, CSS3 and JavaScript.

馃幆 Let's think for a moment: what's it all about? Indeed, wherever the user clicks on the page, a sort of wave pops up and out (the effect).

  • So, we are using JS to check if the user has clicked and, if so, create the wave;
  • The position of this sort of wave has to be in the point clicked by the cursor;
  • Next, the CSS has the role of making the animation and style it , so we can see the effect;
  • Also, when the animation finishes, the wave is vanished from the viewport;

It's pretty much using a simple logic, so let's jump in, I will explain as much as I can.


document.onclick = () => applyCursorRippleEffect(event); 

function applyCursorRippleEffect(e) {
   const ripple = document.createElement("div");

   ripple.className = "ripple";
   document.body.appendChild(ripple); = `${e.clientX}px`; = `${e.clientY}px`; = "ripple-effect .4s  linear";
   ripple.onanimationend = () => document.body.removeChild(ripple);


Enter fullscreen mode Exit fullscreen mode
  • If the user has clicked anywhere in viewport, call the callback function applyCursorRippleEffect(event), as event an object carrying the onclick info;

  • We declare applyCursorRippleEffect(event), wherein ripple is created as a div element, receiving ripple as its class to CSS access it better, and, finally, putting it into the screen;

  • Now, we have something, but no effect yet. The ripple effect has to be in the same local of the mouse cursor. To do so, e.clientX and e.clientY gives us a number that locates the cursor. They are properties of the event. With this info, we can say correctly the left and top of the ripple element. Remember to add px right after such numbers;

  • Next, let's apply the ripple-effect to give magic to the ripple element, as an animation we are soon building with CSS;

  • Lastly, onanimationend tells what ripple element will do after its animation finishes, in this case, disappears from the screen by document.body.removeChild(ripple);;

2nd: CSS

.ripple {
   width: 10px;
   height: 10px;
   background-color: transparent;
   position: fixed;
   border-radius: 50%;
   border: 1px solid $ffffff59;

@keyframes ripple-effect {
   to {
      opacity: 0.01;
Enter fullscreen mode Exit fullscreen mode
  • Now in the .css file the element with class ripple is styled. The width and height are initially set to 15px because the ripple starts little and ends big as we are adding this feature pretty soon. position: fixed; is necessary to fix the element in the position demanded in our script. Despite that, creativity is all opened.

  • Wrapping up, we create the ripple-effect keyframe to say what's about with the animation. transform: scale(15) indicates that ripple will increase as it has to be. You could also increase directly the width and height, but this is not a good practice to animations performance, so here I use transform. Finally opacity accompanied with the increased size makes the ripple effect.

  • Keep in mind that you can make A LOT of really cool combinations, change the ripple shape, color, etc...

鉁旓笍 Windup

I appreciate your visit, and hope you found it interesting or learned something new. Goodbye 馃憢

Top comments (9)

dougwollison profile image
Doug Wollison • Edited

I'd recommend adding on a pointer-events: none so that the ripple div doesn't interfere with other click/hover events that may be obstructed while it's animating (slim chance but annoying if it happens).

darkain profile image
Vincent Milum Jr

Instead of setting display=none, I think it would be better instead to delete the div when it is no longer in use. Otherwise, you're creating memory leaks on the page which could be disastrous for single-page-application web sites.

leonardoschmittk profile image
Leonardo Schmitt

I agree with you, soon trying to edit the post. I believe document.body.removeChild(ripple) would solve it...

lpyexplore profile image

Hello, I am a front-end enthusiast and I am from China. I just read your article and think it is very good. So I want to translate your article into Chinese and publish it on a Chinese blog site. I have nearly 20,000 fan readers. I want to share your article with more people. I want to ask for your information. Opinion, can I do this? Hope to get your reply

leonardoschmittk profile image
Leonardo Schmitt

Of course you can! at ease

z2lai profile image

Keep in mind that width and height animations doesn't have great performance, so it will probably lag a little on mobile. I'm wondering if you can just substitute a transform: scale animation instead.

leonardoschmittk profile image
Leonardo Schmitt

That's a great info. Thanks!

the_riz profile image
Rich Winter

Will this affect page layouts?

leonardoschmittk profile image
Leonardo Schmitt

I believe that depending on the layout, this effect would be kind of strange. Perhaps there are certain places that you don't want to apply the effect, as it happens in all clicks. But it's secure in a way that the layout respect the ripple in all viewports. In fact I didn't realize any occasion wherein the effect avoid some content or functionality. It's open to discussion.