DEV Community

Cover image for How to create horizontal scroll with mouse wheel using JavaScript
Juan Belieni
Juan Belieni

Posted on

How to create horizontal scroll with mouse wheel using JavaScript

Native horizontal scroll with mouse wheel is not so trivial for the user. However, this behavior can be changed using an event listener.

In fact, there are some events involving scrolling and mouse wheel such as mousewheel and DOMMouseScroll. But here I will be using the wheel event.

So, to accomplish this behavior, the JavaScript code will look like this:

element.addEventListener('wheel', (event) => {
  event.preventDefault();

  element.scrollBy({
    left: event.deltaY < 0 ? -30 : 30,
  });
});
Enter fullscreen mode Exit fullscreen mode

Where element is the HTML element that the user will scroll by.

But you can ask why left has static values. That's because different browsers will provide different values for event.deltaY. So it's better to put just one value, only varying when the element is being scrolled to one side or the other.

Result:

Discussion (6)

Collapse
jonrandy profile image
Jon Randy

I think this sort of thing is generally a bad idea. The only good use case I've seen is in those scrolling timeline style stories sometimes found on news sites - where progress through the story is advanced by 'scrolling' down (even though sometimes the scrolling might stop or change direction). With these sites though, it's always quite clear that scrolling 'down' will advanced you through the story, and scrolling up will 'rewind'.

Having this kind of interaction as part of a 'normal' interface is generally quite a jarring experience

Collapse
kcabral profile image
Kalil Cabral

The point of this for me is to make it less inconvenient for people with a mouse to scroll sideways without bothering people using a trackpad.

The issue with this solution is that if the user actually scrolls left or right, the content will always scrolls right (event.deltaY will be 0).

I also think it's way more natural if scrolling down scrolls the content right.

Here's is how I'd do it:

// Only works if scroll was _started inside the element_.

function force_scroll_sideways(element) {
  element.addEventListener("wheel", (event) => {
    event.preventDefault();

    let [x, y] = [event.deltaX, event.deltaY];
    let magnitude;

    if (x === 0) {
      magnitude = y > 0 ? -30 : 30;
    } else {
      magnitude = x;
    }

    //console.log({ x, y, magnitude });
    element.scrollBy({
      left: magnitude
    });
  });
}
Enter fullscreen mode Exit fullscreen mode
Collapse
moopet profile image
Ben Sinclair

Why would you want to associate one hand movement with a different axis? And how does this behave with a touchpad or screen, where you'd be swiping from side-to-side?

Collapse
juanbelieni profile image
Juan Belieni Author

I've tested it with a screen, and it works well. But you're right, when user moves side-to-side with touchpad, it doesn't work, because of the preventDefault. When I have the time, I will update the post to include this information. Thanks!

Collapse
thunderpigeon profile image
nico

Thanks for this great post. @juanbelieni

Element wheel is currently not supported on IOS safari.
Do you perhaps know a workaround for IOS Safari?

Image description

Collapse
sanneh2 profile image
sanneh2

Exceptional performance. What a simple and robust solution to such a profound problem! Well done!