Mouseover listener offsetting coordinates for custom cursor

I’m pulling my second late nighter trying like crazy to get the last bug out of a site I built that I’m now updating & I am just about ready to pull my hair out over this one.

Live Link - with problem present

If you scroll down the page a little, you will see that I am implementing a system where the client can upload their own image’s for their restaurant’s weekly menu. Everything is going swimmingly there, but I am trying to make it so when the end user hovers over the left or right side of the menu’s image, it displays the custom arrow cursor with it’s specific direction related class. We’re still good there. The problem is two things:

  • The custom cursor ( class name .arrow-cursor ) is not staying within the confines of the menu image container. Seems like a dumb thing, but it is tripping out my OCD watching this custom cursor going outside the image that it’s supposed to be navigating behind it.
  • And much MUCH more important, and crucial REAL ISSUE… I can NOT seem to get the custom cursor to display in the proper location. No matter what, it is always offset way to the right and down from where the actual user’s mouse is. No good. This is the bigger of the two requirements that I can’t get figured out.

As a side note, I have a fully functional codepen version of this build, but once I pull everything into wordpress where there are several more layers of html elements surrounding this area, things go foobar bad.

Codepen - Simplified working example

Any and ALL help appreciated. The site uses both vanilla javascript & jQuery. I am still a javascript novice after decades of working with it, I can write it, I can read it, but sometimes can not wrap my head around it. HELP! Please.

Below is the script where the mousemove function is being called.

var swiper = new Swiper('.swiper-container', {
        slidesPerView: 1,
        loop: true,
        speed: 0,
        navigation: {
          nextEl: '.swiper-button-next',
          prevEl: '.swiper-button-prev',
        },
      });
      let cursor = document.querySelector('.arrow-cursor');
      document.addEventListener('mousemove', moveCursor);
      function moveCursor(e) {
        let x = e.clientX;
        let y = e.clientY;

        cursor.style.left = `${x}px`;
        cursor.style.top = `${y}px`;
      }
      let links = Array.from(document.querySelectorAll('.swiper-button-ctrl'));
      links.forEach((link) => {
        link.addEventListener('mouseover', () => {
          if (link.classList.contains('swiper-button-prev')) {
            cursor.classList.remove('cursor-next');
            cursor.classList.add('cursor-prev');
          }
          if (link.classList.contains('swiper-button-next')) {
            cursor.classList.remove('cursor-prev');
            cursor.classList.add('cursor-next');
          }
          cursor.classList.add('active');
        });
        link.addEventListener('mouseleave', () => {
          if (link.classList.contains('swiper-button-prev')) {
            cursor.classList.remove('cursor-prev');
          }
          if (link.classList.contains('swiper-button-next')) {
            cursor.classList.remove('cursor-next');
          }
          cursor.classList.remove('active');
        });
      });

Why are we binding a mousemove to the document for movement over the menu?

Anyway.

0,0 in your coordinate system for arrow-cursor is the top-left corner of the menu container (I’m… not entirely sure why, as the arrow is positioned with fixed, but…). Your code takes the mouse’s position on the screen. Try using offsetX and offsetY instead.

The problem is that you are placing the cursor with position:fixed but you have a parent called .viewport{} (and .viewport.is.loaded{}) which both add transforms to that section. When you add a transform to a parent of fixed element the viewport no longer becomes the reference point but rather that transformed parentis now the viewport. This results in your co-ordinates being offset from the top of that element and not the top of the viewport.

If you remove the transforms from .viewport{} (and .viewport.is.loaded{}) then the cursor will work ok. Of course that will change whatever those transforms were doing.

That’s why it works ok in the codepen as you don’t have the css for .viewport applied.

2 Likes

Thank you so much! Totally solved my issue! You’re a legend bud :fist_left:t2::fist_right:t3:

Honestly, I’m not sure why I binded the mousemove event to the document. I should have done just the swiper/menu area. Thank you for the tip.