April 8, 2026IntermediateCursor Effects
Blurry Cursor
A custom cursor that uses GSAP and linear interpolation (lerp) for a smooth trailing follow effect. When the cursor enters the heading, it expands to 400px and blurs, creating a color-inverted spotlight via mix-blend-mode: difference.
Preview
Hover
Motion Forward
Design studio
Source
"use client";
import { useEffect, useRef, useState } from "react";
import gsap from "gsap";
import styles from "./styles.module.css";
const lerp = (x, y, a) => x * (1 - a) + y * a;
export default function BlurryCursor() {
const demoRef = useRef(null);
const circleRef = useRef(null);
const mouse = useRef({ x: -200, y: -200 });
const delayed = useRef({ x: -200, y: -200 });
const rafId = useRef(null);
const [isActive, setIsActive] = useState(false);
useEffect(() => {
const el = demoRef.current;
if (!el) return;
// Animate in RAF — lerp delayed position toward real mouse position
const animate = () => {
delayed.current = {
x: lerp(delayed.current.x, mouse.current.x, 0.075),
y: lerp(delayed.current.y, mouse.current.y, 0.075),
};
gsap.set(circleRef.current, {
x: delayed.current.x,
y: delayed.current.y,
xPercent: -50,
yPercent: -50,
});
rafId.current = requestAnimationFrame(animate);
};
const onMove = (e) => {
const rect = el.getBoundingClientRect();
mouse.current = { x: e.clientX - rect.left, y: e.clientY - rect.top };
};
const onLeave = () => {
mouse.current = { x: -200, y: -200 };
setIsActive(false);
};
el.addEventListener("mousemove", onMove);
el.addEventListener("mouseleave", onLeave);
rafId.current = requestAnimationFrame(animate);
return () => {
el.removeEventListener("mousemove", onMove);
el.removeEventListener("mouseleave", onLeave);
cancelAnimationFrame(rafId.current);
};
}, []);
return (
<div ref={demoRef} className={styles.demo}>
{/* Text to hover — triggers cursor expansion */}
<p className={styles.label}>Hover</p>
<h1
className={styles.heading}
onMouseOver={() => setIsActive(true)}
onMouseLeave={() => setIsActive(false)}
>
Motion Forward
</h1>
<p className={styles.sub}>Design studio</p>
{/* Custom cursor — position: absolute within demo container */}
<div
ref={circleRef}
className={`${styles.cursor} ${isActive ? styles.cursorActive : ""}`}
/>
</div>
);
}
Dependencies
gsap