Methods for creating custom cursors:

For explanation, check the video

1. Pure CSS

The simplest and easiest way.

body, a {
  cursor: url(https://url-of-your-image.svg), auto;
}

2. Webflow animations

More flexibility, simple implementation - sometimes janky

CSS

.custom-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

3. Javascript

More flexibility - harder to implement

CSS

.js-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

Javascript

const cursor = document.querySelector('.js-cursor')
window.addEventListener('mousemove', (e)=> {
  cursor.style.top = e.y + 'px'
  cursor.style.left = e.x + 'px'
})

4. GSAP

More flexibility & better performance - harder to implement

CSS

.gsap-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

Javascript

// if you want it to delay a but behind your mouse movements
const cursor = document.querySelector('.gsap-cursor')

const xTo = gsap.quickTo(cursor, 'x', {
  duration: 0.3, 
  ease: 'power3.out' 
})

const yTo = gsap.quickTo(cursor, 'y', {
  duration: 0.3, 
  ease: 'power3.out' 
})

window.addEventListener('mousemove', (e) => {
  xTo(e.x)
  yTo(e.y)
})

or

// if you want it to directly follow your movements
const cursor = document.querySelector('.gsap-cursor')
const xSetter = gsap.quickSetter(cursor, 'x', 'px')
const ySetter = gsap.quickSetter(cursor, 'y', 'px')

window.addEventListener('mousemove', (e) => {  
  xSetter(e.x)
  ySetter(e.y)
})