<h1>Ripple Click Effect</h1>

  <ul>
    <li><a>Dashboard</a></li>
    <li><a>My Account</a></li>
    <li><a>Direct Messages</a></li>
    <li><a>Chat Rooms</a></li>
    <li><a>Settings</a></li>
    <li><a>Logout</a></li>
  </ul>
/*custom fonts - Bitter, Montserrat*/
@import url('https://fonts.googleapis.com/css?family=Montserrat|Bitter');
/*basic reset*/
* {margin: 0; padding: 0;}
body {
  background: url('http://thecodeplayer.com/u/m/b1.png') no-repeat center center fixed;
  background-size: cover;
}

h1 {
  font: normal 32px/32px Bitter; color: white;
  text-align: center; padding: 85px 100px;
}

/*nav styles*/
ul {
  background: white; border-top: 6px solid hsl(180, 40%, 60%);
  width: 200px; margin: 0 auto;
}
ul li {
  list-style-type: none;
  /*relative positioning for list items along with overflow hidden to contain the overflowing ripple*/
  position: relative;
  overflow: hidden;
}
ul li a {
  font: normal 14px/28px Montserrat; color: hsl(180, 40%, 40%);
  display: block; padding: 10px 15px;
  text-decoration: none;
  cursor: pointer; /*since the links are dummy without href values*/
  /*prevent text selection*/
  user-select: none;
  /*static positioned elements appear behind absolutely positioned siblings(.ink in this case) hence we will make the links relatively positioned to bring them above .ink*/
  position: relative;
}

/*.ink styles - the elements which will create the ripple effect. The size and position of these elements will be set by the JS code. Initially these elements will be scaled down to 0% and later animated to large fading circles on user click.*/
.ink {
  display: block; position: absolute;
  background: hsl(180, 40%, 80%);
  border-radius: 100%;
  transform: scale(0);
}
/*animation effect*/
.ink.animate {animation: ripple 0.65s linear;}
@keyframes ripple {
  /*scale the element to 250% to safely cover the entire link and fade it out*/
  100% {opacity: 0; transform: scale(2.5);}
}
/* Adapted from http://thecodeplayer.com/walkthrough/ripple-click-effect-google-material-design */ 

"use strict";

    const links = document.querySelectorAll("ul li a");

    function animate (e) {
      const parent = this.parentNode;

      if (parent.querySelectorAll(".ink").length === 0) {
        const span = document.createElement("span");
        span.classList.add("ink");
        parent.insertBefore(span, parent.firstChild);
      }

      const ink = parent.querySelectorAll(".ink")[0];

      ink.classList.remove("animate");

      if (!ink.offsetHeight && !ink.offsetWidth) {
        const d = Math.max(parent.offsetHeight, parent.offsetWidth);
        ink.style.height = `${d}px`;
        ink.style.width = `${d}px`;
      }

      const rect = parent.getBoundingClientRect();

      const offset = {
        top: rect.top + document.body.scrollTop,
        left: rect.left + document.body.scrollLeft
      }

      const x = e.pageX - offset.left - ink.offsetWidth / 2;
      const y = e.pageY - offset.top - ink.offsetHeight / 2;


      ink.style.top = `${y}px`;
      ink.style.left = `${x}px`;
      ink.classList.add("animate");
    }

    links.forEach(link => link.addEventListener("click", animate));

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.