JSFiddle - React, Tailwind, and code Playground
HTML
<img src="//placehold.it/250x200" alt="" class="image">
<img src="//placehold.it/250x200" alt="" class="image">
<div class="circle-cursor circle-cursor--inner"></div>
<div class="circle-cursor circle-cursor--outer"></div>
CSS
body {
margin: 0;
--cursor-color: #000;
}
.circle-cursor {
position: fixed;
left: 0;
top: 0;
pointer-events: none;
border-radius: 50%;
transition: background-color 300ms;
}
.circle-cursor--inner {
width: 5px;
height: 5px;
left: -2.5px;
top: -2.5px;
z-index: 11000;
background-color: var(--cursor-color);
}
.circle-cursor--inner.circle-cursor--hover {
background-color: rgba(0,0,0,0);
}
.circle-cursor--outer {
width: 30px;
height: 30px;
left: -15px;
top: -15px;
border: 1px solid var(--cursor-color);
z-index: 12000;
opacity: 0.2;
}
.circle-cursor--outer.circle-cursor--hover {
background-color: var(--cursor-color);
}
JavaScript
const cursorInner = document.querySelector('.circle-cursor--inner');
const cursorOuter = document.querySelector('.circle-cursor--outer');
let mx = window.innerWidth / 2;
let my = window.innerHeight / 2;
let cxi = mx, cyi = my, cxo = mx, cyo = my;
window.addEventListener('mousemove', (event) => {
mx = event.clientX;
my = event.clientY;
});
function update() {
const dxi = (mx - cxi) * 0.2;
const dyi = (my - cyi) * 0.2;
cxi += dxi;
cyi += dyi;
const dxo = (mx - cxo) * 0.07;
const dyo = (my - cyo) * 0.07;
cxo += dxo;
cyo += dyo;
cursorOuter.style.transform = `translate(${cxo}px, ${cyo}px)`;
cursorInner.style.transform = `translate(${cxi}px, ${cyi}px)`;
requestAnimationFrame(update);
}
requestAnimationFrame(update);
document.body.addEventListener('mouseover', (event) => {
if (!event.target.closest('.image')) return;
cursorInner.classList.add('circle-cursor--hover');
cursorOuter.classList.add('circle-cursor--hover');
});
document.body.addEventListener('mouseout', (event) => {
if (!event.target.closest('.image')) return;
cursorInner.classList.remove('circle-cursor--hover');
cursorOuter.classList.remove('circle-cursor--hover');
});