Skip to content

Instantly share code, notes, and snippets.

@vielhuber
Last active June 16, 2022 16:28
Show Gist options
  • Save vielhuber/6a894f6fa083949f6a3b4ea4c8a350fe to your computer and use it in GitHub Desktop.
Save vielhuber/6a894f6fa083949f6a3b4ea4c8a350fe to your computer and use it in GitHub Desktop.
on mousewheel vanilla js scroll horizontally #js
document.addEventListener('wheel', function(e)
{
if(e.type != 'wheel')
{
return;
}
let delta = ((e.deltaY || -e.wheelDelta || e.detail) >> 10) || 1;
delta = delta * (-300);
document.documentElement.scrollLeft -= delta;
// safari needs also this
document.body.scrollLeft -= delta;
e.preventDefault();
});
@Marvino-il-Marziano
Copy link

On my MacOS 10.14.6, this works on Safari but not Chrome+Firefox.

Previously I had (targeting my HTML div called 'main')
`window.scrollTo(0, 0);
var item = document.getElementsByTagName('main')[0];

window.addEventListener('wheel', function(e) {
	if (e.deltaY > 0) item.scrollLeft += 100;
	else item.scrollLeft -= 100;
});`

which did the reverse --- work on Chrome+Firefox, but not Safari. Your mileage may vary.

@vielhuber
Copy link
Author

Hi! Thanks for your feedback.

I've just tested everything on MacOS 10.13.4 and Chrome 80 + Firefox 70 + Safari 11.1.
Everything works on my end.

Can you try this out and report back if it is really not working?
https://vielhuber.de/playground/mousewheel/

@Marvino-il-Marziano
Copy link

Hello --- I confirm it works fine on my 10.14.6 Mac (+FF70 etc).

I think my problem was purely in my own CSS: I discovered that what I was trying to use didn't work because scrollLeft remained at 0 stubbornly because Safari interpreted the element as having 'overflow: none;' while the other browsers interpreted it as 'overflow: hidden;' --- not sure who at fault there (it shouldn't be ambiguous!), but setting that overflow to 'auto' made it all work & I'm using it in production.

I'll try for a while to re-construct my HTML+CSS as of 2-to-3 days ago (to reproduce my problem with your version), and track down the cause; but I'm not sure I can do that. But essentially it's good to check what happens with your script if you get a vertical overflow (e.g., by putting a 100vh div inside a 100vh div without explicit box-sizing: border-box; or more naturally by the user not checking for this possibility, e.g. tall image in a low browser) then you have two scroll bars suddenly and it jams.

Copy link

ghost commented Jun 24, 2020

Works like a charm! Thanks!

One question, is it possible to continue to scroll vertically after scrolling to the end in the horizontal direction?

@vielhuber
Copy link
Author

vielhuber commented Jun 24, 2020

Yes, just check the vertical scroll position and don't execute the function above if you passed the end.

Pseudo code:

document.addEventListener('wheel', function(e)
{
  if(e.type != 'wheel')
  {
    return;
  }
  if( scrollPositionIsAtTheEnd ) {
    return;
  }
  let delta = ((e.deltaY || -e.wheelDelta || e.detail) >> 10) || 1;
  delta = delta * (-300);
  document.documentElement.scrollLeft -= delta;    
  // safari needs also this
  document.body.scrollLeft -= delta;    
  e.preventDefault();
});

You then have to also check when you again scroll up, but I leave the implementation to you. :)

@woodydaniel
Copy link

@themevan did you manage to implement that code?
I’m wanting the same functionality but not fully understanding the pseudo code posted.

@vielhuber
Copy link
Author

@woodydaniel the idea is to entirely skip that function and not to call e.preventDefault when you have reached the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment