<div class="container">
  <h1>
    Please move around and click anywhere
  </h1>
</div>
<div class="cursor">
    <div class="cursor__default">
      <span class="cursor__default__inner"></span>
    </div>
    <div class="cursor__trace">
      <span class="cursor__trace__inner"></span>
    </div>
  </div>
html, body {
  height: 100%;
  background: black;
}

body {
  cursor: none !important;
}

.cursor {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 9999;
}

.cursor__default__inner {
  position: absolute;
  display: inline-block;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  background: white;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  z-index: 9998;
}

.cursor__trace__inner {
  position: absolute;
  display: inline-block;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  background: blue;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition: transform 0.3s;
}

.cursor--active .cursor__trace__inner {
  transform: translate(-50%, -50%) scale(10);
  transition: transform 0.3s;
}

.ripple {
  position: absolute;
  width: 20px;
  height: 20px;
  background: skyblue;
  border-radius: 50%;
  pointer-events: none;
  animation: ripple 0.5s ease forwards;

}

@keyframes ripple {
  to {
    width: 200px;
    height: 200px;
    margin-left: -100px;
    margin-top: -100px;
    opacity: 0;
  }
}

h1 {
  font-weight: bold;
  font-family: sans-serif;
  color: white;
  padding: 1rem;
  text-align: center;
  width: 100%;
}
document.addEventListener('DOMContentLoaded', function() {
  document.addEventListener('mousemove', function(event) {
    const cursorDefaultInner = document.querySelector('.cursor__default__inner')
    const cursorTraceInner = document.querySelector('.cursor__trace__inner')

    cursorDefaultInner.style.left = event.clientX + 'px'
    cursorDefaultInner.style.top = event.clientY + 'px'

    cursorTraceInner.style.left = event.clientX + 'px'
    cursorTraceInner.style.top = event.clientY + 'px'
  })

  const cursor = document.querySelector('.cursor')

  document.addEventListener('mousedown', function() {
    cursor.classList.add('cursor--active')
  })

  document.addEventListener('mouseup', function() {
    cursor.classList.remove('cursor--active')
  })

  function createRipple(e) {
    let ripple = document.createElement('div')

    ripple.classList.add('ripple')

    cursor.appendChild(ripple)

    ripple.style.top = (e.clientY - ripple.clientHeight / 2) + 'px'
    ripple.style.left = (e.clientX - ripple.clientWidth / 2) + 'px'
  }

  document.addEventListener('click', function(e) {
    createRipple(e)
  })
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.