Tilting Cursor effect with CSS and JS

annetawamono

Anneta Wamono

Posted on June 27, 2023

Tilting Cursor effect with CSS and JS

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. 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.

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

The 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>
Enter fullscreen mode Exit fullscreen mode

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.
.cursor svg {
    width: 100px;
}
Enter fullscreen mode Exit fullscreen mode
  • 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.
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)`;
});
Enter fullscreen mode Exit fullscreen mode

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.
.cursor svg {
    /* block elements have a width and height value needed for transformations */
  display: block;
  transform-origin: top left;
}
Enter fullscreen mode Exit fullscreen mode
  • 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.
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;
}
Enter fullscreen mode Exit fullscreen mode

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!

💖 💪 🙅 🚩
annetawamono
Anneta Wamono

Posted on June 27, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related