How to add a Custom Cursor in NextJS Application?

What will we build?

We will add a Custom Cursor to our NextJS application. I will be using the custom index file provided by NextJS and add the custom cursor to it, but you can add the cursor to any file by following the same steps.

Custom cursor on the NextJS page

You can find the live demo over here.

Let’s Start!

Finishing off the basics first, we will quickly create a new Next Application and remove the unnecessary files from it.

npx create-next-app custom-cursor-demo

After the application is created remove, the api folder from pages directory and create a new directory named components (this is where we will add our custom cursor) in the root directory.

This is how your final directory should look:

Final Directory of the project

Next create a file named Cursor.js in your components directory and export a default function based component returning a div with className = ‘cursor’.

Custom Cursor component

Now we will give some styling to this element in our styles/global.css directory:

.cursor {
width: 20px;
height: 20px;
border: 1px solid white;
border-radius: 50%;
position: absolute;
pointer-events: none;
.cursor::after {
content: "";
width: 20px;
height: 20px;
position: absolute;
border: 2px solid blue;
border-radius: 50%;
opacity: .5;
top: -8px;
left: -8px;
@keyframes cursorAnim {
0% {
transform: scale(1);
50% {
transform: scale(5);
100% {
transform: scale(1);
opacity: 0;
.expand {
animation: cursorAnim .5s forwards;

In this file the things to note are that on click of the element, we have added a custom class named “expand” to the element so that it gives us an effect on click which you can notice in the demo. All the other attributes of the CSS are self-explanatory.

But now comes the main part, how will we track the mouse and shift our element according to it?

For that we will use the react useRef hook to reference the element and the useEffect hook to add the logic for changing the position of the element and add the CSS class “expand” onClick.

Here is the code to it:

export default function CustomCursor() {
const cursorRef = useRef(null)
useEffect(() => {
if (cursorRef.current == null || cursorRef == null)
document.addEventListener('mousemove', e => {
if (cursorRef.current == null)
cursorRef.current.setAttribute("style", "top: " + (e.pageY) + "px; left: " + (e.pageX) + "px;")
document.addEventListener('click', () => {
if (cursorRef.current == null)
setTimeout(() => {
if (cursorRef.current == null)
}, 500)
}, [])
return (
<div className='cursor' ref={cursorRef}>

The things to note here are that everytime we are checking whether the “cursorRef” is null or not. This is because, whenever we use this component in different pages the useEffect hook is run again, which is why we need to discard all the requests made by any null reference of the “cursorRef”. Next thing to note is that we are using a set timeout to remove the expand class again from the element. This is because if we don’t do it, the “expand” class will continously append over the element, resulting in errors, therefore we are removing this class every time our animation gets completed. All the other code is basic JS and self-explanatory.

So now, that we have our custom cursor’s component ready, the next step is to add this component in our index.js file.

The process is same as importing any other component.

First import the component, and then use it the main element:

import CustomCursor from ‘../components/Cursor’

Now add it into the main element of our file:

<main className={styles.main}>
<CustomCursor />
<h1 className={styles.title}>
Welcome to <a href=”">Next.js!</a>

Congratulations 🥳, you have successfully added the cursor to your NextJS application.


You can now use this CustomCursor component in any page and add your custom cursor. This way you can add more customization to your pages and make them feel more attractive. The GitHub repository for the code is here.

What Next?

We have just made a simple cursor but you can add a lot of customization to your Cursor and make them look more attractive like adding a delay and infinite heart beating css etc.

Happy Coding :)