Follow pointer with spring: Step-by-step tutorial

Matt Perry

In this tutorial, we're going to build the Follow pointer with spring example step-by-step.

This example is rated 2/5 difficulty, which means we'll spend some time explaining the Motion APIs we've chosen to use, but it assumes familiarity with JavaScript as a language.

Here's a live demo of the example we're going to be creating:

Loading...

Introduction

The Follow Pointer with Spring example shows how to make an element smoothly follow your cursor with a spring-like motion. This creates a natural, physical feeling as the element trails behind your mouse movements.

This example uses two key Motion APIs:

  • useSpring - To create spring physics-based animation

  • frame - For efficient, batched DOM reads and writes

Spring animations are a great way to add natural motion to your UI because they mimic the behavior of real-world physics. Unlike linear or easing animations, springs respond to changes in velocity, making the motion feel more organic, especially when following user input like mouse movement.

Get started

Let's start by creating a basic component with a ball that will follow our pointer:

"use client"

import { motion } from "motion/react"
import { useRef } from "react"

export default function Drag() {
    const ref = useRef<HTMLDivElement>(null)

    return <motion.div ref={ref} style={ball} />
}

const ball = {
    width: 100,
    height: 100,
    backgroundColor: "#5686F5",
    borderRadius: "50%",
}

This gives us a simple blue circle on the screen, but it doesn't follow our pointer yet.

Let's animate!

Import from Motion

First, we need to import the additional Motion APIs we'll be using:

import { frame, motion, useSpring } from "motion/react"

Creating the spring motion values

Now we'll create a custom hook that will handle the pointer-following logic:

function useFollowPointer(ref) {
    const x = useSpring(0)
    const y = useSpring(0)

    // We'll add event handling here

    return { x, y }
}

The useSpring hook creates a special type of motion value that animates changes using spring physics. By default, whenever we set a new value, the motion value will animate to that target with a natural spring motion rather than jumping instantly.

Customizing the spring

Let's add some spring configuration to control how the following behavior feels:

const spring = { damping: 3, stiffness: 50, restDelta: 0.001 }

function useFollowPointer(ref) {
    const x = useSpring(0, spring)
    const y = useSpring(0, spring)

    // We'll add event handling here

    return { x, y }
}

The spring configuration controls:

  • damping: How quickly the spring settles (lower values create more bounce)

  • stiffness: The strength of the spring (higher values make it more responsive)

  • restDelta: When to consider the animation complete (smaller values prevent "snapping" at the end of the animation, but make the animation continue for longer)

Adding pointer tracking

Now we need to track the mouse pointer and update our spring values accordingly:

useEffect(() => {
    if (!ref.current) return

    const handlePointerMove = ({ clientX, clientY }) => {
        const element = ref.current

        frame.read(() => {
            x.set(clientX - element.offsetLeft - element.offsetWidth / 2)
            y.set(clientY - element.offsetTop - element.offsetHeight / 2)
        })
    }

    window.addEventListener("pointermove", handlePointerMove)

    return () => window.removeEventListener("pointermove", handlePointerMove)
}, [])

This is fairly standard but pay attention to frame.read. We use this to place the callback on the "read" part of Motion's render loop. This ensures we only update the motion values once per frame, reducing unnecessary work.

Using the motion values

Finally, let's update our component to use our custom hook:

export default function Drag() {
    const ref = useRef<HTMLDivElement>(null)
    const { x, y } = useFollowPointer(ref)

    return <motion.div ref={ref} style={{ ...ball, x, y }} />
}

When we pass our motion values directly to the style prop, Motion automatically uses them to drive the transforms of the element. As the values update with spring physics, the element will move accordingly.

Conclusion

In this tutorial, we learned how to create a UI element that follows the pointer with natural spring physics. We used:

  • useSpring to create motion values that animate changes with spring physics

  • frame.read() to efficiently batch DOM reads

  • Motion's ability to accept motion values directly in the style prop

This technique can be used for various interactive UI elements like hover effects, custom cursors, or draggable elements with inertia. By adjusting the spring configuration, you can create different feels - from tight, responsive following to loose, bouncy motion.

Motion is supported by the best in the industry.

Stay in the loop

Subscribe for the latest news & updates.

Stay in the loop

Subscribe for the latest news & updates.

Stay in the loop

Subscribe for the latest news & updates.