Customise Cursor
Tags: react, javascript, css, beginners
Published: 2022-01-12 07:28:08

Here's some context before we start. <br/>
Got inspired to customise the typical cursor we all use. Googled, researched, watched videos but found nothing worthwhile. 

So here's an article on building your own fancy cursor.
<hr/>

## Here's what we are building today.
<a href="https://www.loom.com/share/1c11ace26c464a30bb7475b5f501168c">
    <p>Custom Cursor - Watch Video</p>
    <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/1c11ace26c464a30bb7475b5f501168c-with-play.gif">
  </a>

## Let's Begin:
Here's the overview:
- The fancy cursor you see above is nothing but 2 `div`s styled in a way to appear like a *ring* & a *dot*.
- Track the position of the original cursor.
- Displace your customised cursor as per the position of the original cursor.
- And finally, hide the original cursor.

Yes, it is that simple.

<hr/>

### The `CustomCursor` Component:
Reverse Engineering it.<br/>
We will be importing our `CustomCursor` Component in the `app.js` in the following manner:
```js
import "./App.css";
import CustomCursor from "./components/customCursor";

function App() {
  return (
    <div className="App">
      <CustomCursor />
       {/* Rest of your code */}
    </div>
  );
}

export default App;
```

Now, let's build our component.

<hr/>

### Track the position:

Firstly, we need to track the **position **of our original cursor and hence we will displace our custom cursor with respect to the **position** tracked.

- Use the `mousemove` event listener to grab **x & y co-ordinates** of the original cursor.
- Store them in a state variable using `useState`. Here we are naming it `position`.
```js
const [position, setPosition] = useState({ x: 0, y: 0 });

 useEffect(() => {
 document.addEventListener("mousemove", (event) => {
      const { clientX, clientY } = event;
      setPosition({ x: clientX, y: clientY });
    })
 })
```

`clientX` & `clientY` are the **X & Y Position Coordinates** extracted from `event`

Tip: `console.log` to check if you are able to access the co-ordinates

<hr/>

### Build a Basic Custom Cursor:
- Create a `div`(will style it as desired later).
- Displace it using the `position`state variable(extracted from the event listener above).
 - To move the `div` around we'll use `top` & `left` **CSS properties** combined with `position:fixed`
 - `position:fixed` will remove the `div` from the normal document flow.

```js
<div style={{ left: position.x, top: position.y, position:fixed}}>
  Cursor
</div>
```

Put the pieces together and you'll get a cursor like this 👇
<a href="https://www.loom.com/share/bd183063b2904be99768710f090a292d">
    <p>Basic Custom Cursor - Watch Video</p>
    <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/bd183063b2904be99768710f090a292d-with-play.gif">
  </a>

That's some good progress. Let's keep going.
<hr/>

### Style the Custom Cursor:
It's time to beautify our cursor. Use all of your creativity and design a fancy cursor.

I'll just be styling the `div`s to appear like a *ring* & *dot*

Here's how the `jsx` looks like.

```jsx
<div className="cursor ring" style={{ left: position.x, top: position.y }} />
<div className="cursor dot" style={{ left: position.x, top: position.y }} />
```
And here's the CSS styling.

```css

.cursor {
  position: fixed;
}

.ring {
  width: 22px;
  height: 22px;
  border: 2px solid rgba(165, 160, 160, 0.808);
  border-radius: 100%;
  transform: translate(-50%, -50%);
  -webkit-transition-duration: 100ms;
  transition-duration: 100ms;
  -webkit-transition-timing-function: ease-out;
  transition-timing-function: ease-out;
  will-change: width, height, transform, border;
  z-index: 999;
}

.dot {
  width: 8px;
  height: 8px;
  background-color: rgb(100, 94, 94);
  border-radius: 100%;
  transform: translate(-50%, -50%);
  z-index: 999;
  pointer-events: none;
  transition-duration: 10ms;
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
}
```

And there we are! We have a beautiful custom cursor followed by the original cursor.
<a href="https://www.loom.com/share/cd08890af18e484ebcc7f076562021bb">
    <p>Custom Cursor</p>
    <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/cd08890af18e484ebcc7f076562021bb-with-play.gif">
  </a>
<hr/>

### Hide the Original Cursor
We are almost done. <br/>
We just have to hide the original cursor.

It's quite simple. Here's how we do it.
```css
html {
  cursor: none;
}
```

<hr/>
That's all! We are done. <br/>
Now you can see a beautifully customized cursor with a smooth transition.
<a href="https://www.loom.com/share/1dfff47c1edc4d678f7f2cf69060a9e0">
    <p>Final Cursor - Watch Video</p>
    <img style="max-width:300px;" src="https://cdn.loom.com/sessions/thumbnails/1dfff47c1edc4d678f7f2cf69060a9e0-with-play.gif">
  </a>

Here's the code altogether.
```js

function CustomCursor() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    document.addEventListener("mousemove", (event) => {
      const { clientX, clientY } = event;
      setPosition({ x: clientX, y: clientY });
    });
  }, []);

  return (
  <>
  <div className="cursor ring" style={{ left: position.x, top: position.y }}/>
  <div className="cursor dot" style={{ left: position.x, top: position.y }}/>
  </>
  );
}
```

<hr/>

Hope you found this valuable. <br/>
A huge shoutout to my friend  [Udit](https://twitter.com/uditkumar_01) , The customised cursor on his portfolio got me inspired to build one.

PS: Don't just stop here, as you now know the technique go ahead and use your creativity to the fullest to design a fancy cursor. <br/>
Tip: Try adding animations on the click of the mouse.

<hr/>
That's it from my side today. Let me know your thoughts in the comment section. <br>
If you liked the article give it a thumbs up. 


Hope you enjoyed it, and if you did, consider supporting me 👇. It will make my day :) 

%[https://www.buymeacoffee.com/sayurikamble]