<div class="page"></div>

<div id="cursor"></div>
body {
  margin: 0;
  height: 100vh;
}

.page {
  height: 100%;
  background: url('https://images.unsplash.com/photo-1503431128871-cd250803fa41?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=750&q=90') center / cover;
}

#cursor {
  position: fixed;
  width: 400px;
  height: 400px;
  left: -200px;
  top: -200px;
  background-image: radial-gradient(circle closest-side, rgb(255, 255, 255), rgb(127, 127, 127));
  mix-blend-mode: soft-light;
  pointer-events: none;
}
const cursor = document.querySelector('#cursor');

let mx = window.innerWidth / 2;
let my = window.innerHeight / 2;
let cx = mx, cy = my;

window.addEventListener('mousemove', (event) => {
  mx = event.clientX;
  my = event.clientY;
});

function update() {
  const dx = (mx - cx) * 0.05;
  const dy = (my - cy) * 0.05;
  cx += dx;
  cy += dy;
  
  const speed = Math.min(15, Math.hypot(dx, dy)) / 15;

  cursor.style.transform = `translate(${cx}px, ${cy}px) scale(${0.5 + speed * 0.5})`;
  cursor.style.opacity = speed;
  
  requestAnimationFrame(update);
}

requestAnimationFrame(update);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.