How to prevent a browser from going back/forward in history when scrolling horizontally?

25,862

Solution 1

So I figured since i've created a web app, why not prompt the user for any unsaved changes which will defer the user from loosing any unsaved changes or ending up on the previous or next page in the browser history.

Here is the solution if any one else comes across this problem like I did:

window.onbeforeunload = function(e) {
    return 'Ask user a page leaving question here';
}; 

Solution 2

history.pushState(null, null, location.href);
window.onpopstate = function(event) {
    history.go(1);
};

Demo: http://jsfiddle.net/DerekL/RgDBQ/show/

You won't be able to go back to the previous webpage, unless you spam the back button or hold down the back button and choose the previous entry.

Note: onpopstate (or event onbeforeunload) doesn't seem to work on iOS.

Solution 3

If you're on a mac this is caused by the Track Pad Gestures.

System Preferences -> Trackpad -> More Gestures. 

Not the JS solution you're looking for, but if you just want to prevent it for yourself you can turn the feature off.

Solution 4

Works in Chrome and Safari (i.e tested with Chrome and Safari):

// el === element on which horizontal scrolling is done 
// (can be container of scrolled element or body or any other ancestor)
var preventHistoryBack = function (e) {
  var delta = e.deltaX || e.wheelDeltaX;

  if (! delta) {
    return;
  }

  window.WebKitMediaKeyError /*detect safari*/ && (delta *= -1);

  if (((el.scrollLeft + el.offsetWidth) === el.scrollWidth && delta > 0) || (el.scrollLeft === 0 && delta < 0) ) {
    e.preventDefault();
  }
};
el.addEventListener('mousewheel', preventHistoryBack);

Solution 5

Here's something that may work for you using CSS' overscroll-behaviour property:

Javascript

document.body.style.overscrollBehaviour = "contain";

CSS

body {
    overscroll-behaviour: contain;
}

At the time of writing this, July 10th 2020, this causes scrolling left at the left-end of the page to no longer trigger a backward history-navigation.

I'm not sure what other side-effects this will have on the rest of the user experience. I wish this could be applied inside elements, but it seems like this will only work when applied to the document body.

Share:
25,862
Steve C
Author by

Steve C

Product designer and full-stack developer.

Updated on July 11, 2020

Comments

  • Steve C
    Steve C almost 4 years

    How can one disable a modern browsers default functionality using JQuery or Native JS for going backwards or forwards when scrolling horizontally?

    This usually happens when using a trackpad and when scrolled to the end or start of a scrollable div.

    • SimonDever
      SimonDever about 11 years
      The driver and trackpad software is your overlord. See this question answered.
  • Steve C
    Steve C about 11 years
    No offense but manipulating the browser history like that is very nasty in terms of user experience. It's very confusing and annoying. Can see what your getting at though
  • Steve C
    Steve C about 11 years
    You're exactly right, why would they implement such an annoying way of jumping back and forth in a browser? I think this is so annoying to any user when you are trying to look for something in a horizontal scroll pane.
  • thdoan
    thdoan over 10 years
    You can still go back if you hold down the Back button.
  • hexalys
    hexalys almost 10 years
    @steve It's nasty if done for no reason indeed. But there are legit cases for manipulating it that way, at least temporarily... One case I want to apply this to is for skipping the unwanted history trail from the use of the css :target pseudo-class. Or perhaps, disable history, and provide a custom back button instead.
  • Luke Cousins
    Luke Cousins almost 10 years
    Or when someone is in a payment process and will invalidate their whole payment by using the back button, whereas using the in-page back button will work fine. I can't change the process, it's managed by the payment provider, but I can try to help prevent the user from unknowingly screwing it up!
  • Jacksonkr
    Jacksonkr almost 7 years
    Can also e.preventDefault(); return false;
  • Jacksonkr
    Jacksonkr almost 7 years
    Note, "wheel" and "mouseweel" operate a bit differently: stackoverflow.com/questions/25204282/…
  • Klimashkin
    Klimashkin over 6 years
    It works, but since Chrome 51 you will see '[Violation] Added non-passive event listener to a scroll-blocking 'wheel' event' message in console. But we need nonpassive event, because we call 'preventDefault', and it's unclear how to suppress that message