MdMasud

WordPress, Laravel, Flutter

Custom Cursor Navigation in SwiperJS – What I Built and How I Fixed It

Today, I was working on a custom slider using SwiperJS, and I wanted to do something a bit more interactive than the usual arrows or dots.

Instead of showing fixed navigation arrows, I thought it would be more fun to show floating “Next” and “Previous” text that follow the cursor, depending on which side of the slider you’re hovering. Kind of like a tail that hints where the slider will move if you click.

It turned out to be a really nice effect – but getting it right wasn’t completely straightforward. Here’s how I made it work, and what issues came up along the way.

What I Was Trying to Do

  • Show “Next” on the right side of the slider
  • Show “Previous” on the left
  • Make the text follow the cursor with a smooth animation (like a trailing effect)
  • Hide the floating text when hovering buttons inside each slide (so it doesn’t get in the way)

The First Hurdle: Cursor Trail Jumping or Sticking

At first, I tried updating the cursor-following text using transform: translate(...) inside mousemove, and it seemed okay. But it felt jumpy, and sometimes the text would just snap to the corner or get stuck.

After a bit of testing, I realised the issue was that I was mixing transform with left/top positioning. That doesn’t play well when you’re trying to animate smoothly using requestAnimationFrame.

The Fix: Left & Top + Easing Transition

To get that smooth “trailing” or “wave” motion, I switched to updating left and top with easing. That way, the text glides behind the mouse rather than sticking to it like glue.

This made a big difference. Now the text follows the cursor in a fluid way – not jerky, not laggy, just smooth.

floatX += (mouseX - floatX) * 0.1;
floatY += (mouseY - floatY) * 0.1;

Next Issue: Hovering Over Buttons

Each slide had a button in the bottom-right corner (like “Book Now”). But when you hovered over that button, the floating “Next”/”Previous” text would still be there — not ideal for usability or design.

So I added a simple fix: detect when the user is hovering the button (or the caption area), and hide the floating text during that time.

$(document).on('mouseenter', '.v-pageHead__caption', function () {
	hoveringButton = true;
	$('.floating-nav').css('opacity', 0);
});

$(document).on('mouseleave', '.v-pageHead__caption', function () {
	hoveringButton = false;
});

Now, when you’re over the button, the cursor tail disappears. Clean and and tidy.

Keeping It Clean: Only Run If Slider Is Active

One more thing I wanted to avoid was unnecessary code running on pages where there was only one slide — or no slider at all.

So I wrapped everything inside a conditional check like this:

if ($('.v-pageHead__slide', '.v-pageHead__slider').length > 1) {
	// Only run this whole block if more than 1 slide
}

That way, no Swiper is initialised unless needed, and no extra listeners or animations are running in the background.

Finally, This was a fun little UX tweak — a bit fiddly at times, but the end result feels smooth and adds a nice touch. It’s the kind of detail that makes a site feel that bit more alive.

If you’re using Swiper and fancy something a bit cooler than the usual arrows, give it a try! And if you want a peek at the code, just give me a shout here.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *