How to create a custom cursor with React and Framer-motion
Tags: react, framermotion, animation, javascript
Published: 2022-08-04 14:06:00

In this article, I will guide you through the process of creating a custom cursor for your React application using Framer motion. At the end of the tutorial, you will have built a custom cursor that looks like the following:

![Custom-cursor-Final-gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpuiecg83j52c3dyo55p.gif)

## Prerequisite

To follow along with this tutorial, you’ll need the following:

- A text editor
- Node.js installed locally on your machine
- Working knowledge of HTML, CSS, and JavaScript
- Working knowledge of React

You can find the complete code for this tutorial at this [CodeSandbox](https://codesandbox.io/s/custom-cursor-with-react-and-framer-motion-h40wl5?file=/src/App.js).

Let’s get started!

## Setting up the Project

Now, let’s set up a simple React project and install the necessary dependencies.

We’ll start by installing React:

```bash
npx create-react-app custom-cursor-app
```

Or you can use Yarn

```bash
yarn create react-app custom-cursor-app
```

Next, we’ll install Framer Motion

```bash
npm install framer-motion
```

Or you can use Yarn

```bash
yarn add framer-motion
```

## Getting Started

First, we'll open the App.js file and remove some of the code in it, next we'll replace it with these few lines of code

```javascript
import "./App.css";

const App = () => {
  return (
    <div className="App">
      <h1 className="title">Custom Cursor</h1>
      <div className="cursor"></div>
    </div>
  );
};

export default App;
```

Next, we’ll import everything else that’s required to help us create a custom cursor, from the libraries we installed earlier:

`useState` and `useEffect` Hooks from React.

`motion` Hook from Framer Motion.

```javascript
import { useState, useEffect } from "react";

import { motion } from "framer-motion";
```

Next, open the App.css file and remove the code in it and place these lines of code in the file, this helps us style the App.js file

```css
@import url("https://fonts.googleapis.com/css2?family=Mochiy+Pop+One&display=swap");

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
}

.App {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background-color: aqua;
  font-family: "Mochiy Pop One", sans-serif;
}

.title {
  font-size: 5rem;
}

.cursor {
  background-color: #111;
  height: 16px;
  width: 16px;
  border-radius: 50%;
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
}
```

## Getting the Mouse position

To get the mouse position when running the app, we'll need the useState and useEffect Hooks provided by React.

```javascript
import "./App.css";
import { useState, useEffect } from "react";
import { motion } from "framer-motion";

const App = () => {
// state for mouse position
  const [mousePosition, setMousePosition] = useState({
    x: 0,
    y: 0,
  });

  useEffect(() => {
    const mouseMove = (e) => {
      setMousePosition({
        x: e.clientX,
        y: e.clientY,
      });
    };

    window.addEventListener("mousemove", mouseMove);

    return () => {
      window.removeEventListener("mousemove", mouseMove);
    };
  }, []);

  return (
    <div className="App">
      <h1 className="title">Custom Cursor</h1>
      <div className="cursor"></div>
    </div>
  );
};

export default App;
```

Here, we use the `useState` Hook to set the state for the mouse position.
In the `useEffect` Hook, we are getting the current position of the mouse using the `window` object.
Next, we set the state x and y of the `mousePosition` using the `clientX` and `clientY` method from the event object.
We are now able to track the movement of the mouse on the screen.

## Adding Animations
Next up, we'll be animating the mouse cursor using the motion module we imported from Framer motion.

```javascript
const App = () => {

  // Variant animation
  const variants = {
    default: {
      x: mousePosition.x - 8,
      y: mousePosition.y - 8,
    },   
 };

  return (
    <div className="App">
      <h1 className="title">
        Custom Cursor
      </h1>
// using the motion module to animate the cursor div element
      <motion.div
        className="cursor"
        variants={variants}
        animate="default"
      ></motion.div>
    </div>
  );
};

export default App;
```
Here, we are targetting the cursor element, we create a variant for the cursor animation, and set the default `x` and `y` position of the cursor element using the `mousePosition` state, `mousePosition.x` for the cursor element `x` initial position and `mousePosition.y` for the cursor element `y` initial position.
In the `App.css` file the cursor div element is styled to have a width and height of `16px` each, reducing the `mousePosition.x` and `mousePosition.y` by 8 helps center the mouse cursor in the cursor div element.
Next up, to remove the native browser cursor, in the App.css file paste this line of code.

```css
*,
*::before,
*::after {
  cursor: none;
}
```


## Setting the Mixblendmode
To set the mixBlendMode for the custom cursor, open up the App.js file and edit the code.

```javascript

// Set cursor variant to change color on hover text
const [cursorVariant, setCursorVariant] = useState("default");

// Variant animation
const variants = {

// default animation (applies onMouseLeave)
  default: {
    x: mousePosition.x - 8,
    y: mousePosition.y - 8,
  },

// text animation (applies onMouseEnter) 
  text: {
    height: 150,
    width: 150,
    x: mousePosition.x - 70,
    y: mousePosition.y - 70,
    backgroundColor: "aqua",
    mixBlendMode: "difference",
  },
};

// function for textLeave and textEnter
const textEnter = () => setCursorVariant("text");
const textLeave = () => setCursorVariant("default");

return (
  <div className="App">
    <h1 className="title" onMouseEnter={textEnter} onMouseLeave={textLeave}>
        Custom Cursor
      </h1>
     <motion.div
       className="cursor"
       variants={variants}
       animate={cursorVariant}
     ></motion.div>
  </div>
 );
};
```

First, we create a new state for the cursor animation variant using the `useState` Hook.
Next, we create a function to set the variant animation of the cursor element to `text` animation when the mouse hovers over the h1 element, and we have another function to set the variant animation of the cursor element to `default` when the mouse leaves the h1 element.
Going over the text variant animation, we set the width and height of the cursor element to `150px` each, and reduce the `mousePosition` **`x`** and **`y`** by 70px each to center the cursor.
Next up we give the cursor element a background color of `aqua`, **so when the mouse enters the `h1` element the color changes to `aqua`.**
Finally, we set the `mixBlendMode` property to `difference`.
The mixBlendMode property is what inverts the color of the `h1` text to the `aqua` color onMouseEnter.

Your complete custom cursor webpage should look like this:

![Custom-cursor-Final-gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qobjoiox8acnsxs4xjko.gif)

You can find the complete code for this tutorial at this [CodeSandbox](https://codesandbox.io/s/custom-cursor-with-react-and-framer-motion-h40wl5?file=/src/App.js). 

## Conclusion
Framer motion is an extremely helpful library to use when you want to create animations. You can find a full list of Framer-motion utilities in the animation section of the [documentation](https://www.framer.com/docs/introduction/).

Thanks for reading, and have fun playing around with this and make some tweaks to get a better custom cursor for your webpage!

If you enjoyed reading this as much as I enjoyed writing it, then Like and Share this with your friends and feel free to connect with me on [Twitter](https://mobile.twitter.com/kolsCodes) 👨‍💻.

[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/default-yellow.png)](https://www.buymeacoffee.com/damolausmaN)