Tilting Cursor effect with CSS and JS
Tags: codepen, beginners, javascript, css
Published: 2023-06-27 23:52:31

Welcome to my Frontend Studies - a series where I try to recreate and give general notes on a UI element that inspires me. I hope beginner and intermediate learners can take something away from this, and as well as help me improve in return.

My inspiration for this article is [Studio Brot's website](https://www.studiobrot.de/). I like it a lot because it is a subtle animation effect that results in a pretty fun mouse interaction.

![GIF of cursor tilting left and right along the x-axis of the page. This screenshot is of Studio Brot.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqspkpzmsn8uahedcldz.gif)

I broke down the element into the following parts:
1. Replace cursor with a custom cursor
2. Find your range of rotation
3. Rotate the cursor along the x-axis

{% codepen https://codepen.io/annetawamono/pen/xxJaEoK %}

## The HTML

```html
<div class="cursor">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 550.58 667.15"><path class="d" d="M0,50.09C0,8.48,47.86-14.92,80.7,10.63l450.48,350.41c37.58,29.23,16.91,89.46-30.7,89.46h-228.41c-16.82,0-32.71,7.7-43.14,20.89l-139.7,176.67c-29.4,37.19-89.22,16.4-89.22-31.01V50.09ZM500.48,400.5L50,50.09V617.05l139.7-176.68c19.91-25.18,50.26-39.87,82.36-39.87h228.41Z" fill="currentColor"/></svg>
</div>
```

## Replace cursor with a custom cursor

- Get an SVG cursor. Remember to size it appropriately. My cursor started out much larger than I wanted, so I used CSS to scale it down.

```css
.cursor svg {
	width: 100px;
}
```

- Make your SVG cursor follow your mouse pointer using event listener `mousemove`. The event parameter gives you access to the `clientX` and `clientY` properties which represent the x and y position of your pointer. I'm also using CSS translate property to update the position of the SVG cursor, which can be passed through in JavaScript.
  
```js
const cursor = document.querySelector(".cursor");

document.addEventListener("mousemove", function(e) {
  let clientX = e.clientX;
  let clientY = e.clientY;
  let vw = window.innerWidth;
  
  cursor.style.transform = `translate(calc(${clientX}px), calc(${clientY}px)`;
});
```

## Find your range of rotation

- You'll need to make sure that the tip of the SVG cursor matches the tip of your mouse pointer so that clicking with the SVG cursor feels accurate. CSS has a `transform-origin` property that defines the point all transforms are based on. By default it is in the center of the element, but you can adjust it.

```css
.cursor svg {
	/* block elements have a width and height value needed for transformations */
  display: block;
  transform-origin: top left;
}
```

- Find a range of rotation that suits your new cursor. I chose `52deg`.

## Rotate the cursor along the x-axis

- Find viewport width with `window.innerWidth`.
- Take `clientX` value of your cursor and the viewport width and normalize them to map to your range of rotation. **Normalization is taking any range of values and mapping it to the range of 0 to 1.** The result is that when you input a value within your initial range, you get a corresponding output value between 0 and 1. So in our code, our initial range is 0 to our viewport width. We pass the x position into our normalize function so that it returns a number between 0 and 1. We can then take that number and multiply it with our range of rotation `52deg` so that we can get the correct degree of rotation at our mouse's x position.
- Pass that degree to our SVG cursor as a CSS property.

```js
const cursor = document.querySelector(".cursor");

document.addEventListener("mousemove", function(e) {
  let clientX = e.clientX;
  let clientY = e.clientY;
  let vw = window.innerWidth;
  
  cursor.style.transform = `translate(calc(${clientX}px), calc(${clientY}px)`;
  
  let rotation = Math.round(52 * normalize(clientX, vw));
  
  cursor.style.setProperty("--cursor-rotate", `${rotation}deg`);
});

function normalize(curr, max) {
  return curr / max;
}
```

## Takeaways

When I first saw this effect my gut reaction was "I totally know how to do that". I had enough knowledge to already piece together how I was going to achieve this without needing to do a ton of research. I think this signaled to me that my skillset was improving.

---
*Thank you for reading my article. If there is anything you would like more details on, leave a comment below. I'd like to continue improving the quality of my articles, so any feedback is appreciated.*

*See you at the next one!*