21

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.

Steve C
  • 2,638
  • 3
  • 25
  • 27
  • 2
    The driver and trackpad software is your overlord. See this [question answered](http://stackoverflow.com/questions/14086337/is-it-possible-to-have-gestures-with-trackpads). – AmbrosiaDevelopments Apr 24 '13 at 03:48

5 Answers5

23
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.

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • 4
    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 Apr 25 '13 at 00:34
  • 4
    You can still go back if you hold down the Back button. – thdoan Aug 15 '13 at 02:12
  • 1
    @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](https://developer.mozilla.org/en-US/docs/Web/CSS/:target) pseudo-class. Or perhaps, disable history, and provide a custom `back button` instead. – hexalys Jun 19 '14 at 00:42
  • 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! – Luke Cousins Jun 19 '14 at 08:56
8

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';
}; 
Steve C
  • 2,638
  • 3
  • 25
  • 27
5

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.

AndrewHipp
  • 379
  • 2
  • 6
  • 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. – Steve C Apr 25 '13 at 00:55
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);
avetisk
  • 11,651
  • 4
  • 24
  • 37
  • 1
    Note, "wheel" and "mouseweel" operate a bit differently: https://stackoverflow.com/questions/25204282/mousewheel-wheel-and-dommousescroll-in-javascript – Jacksonkr Aug 02 '17 at 18:43
  • 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 – Klimashkin Sep 22 '17 at 01:18
4

Here's something that may (or may not) work for you using CSS' overscroll-behavior-x property. The linked MDN article goes into more detail, has usage examples, and browser support information.

Experiment with either the value contain or none. Quoting from the MDN link,

contain: Default scroll overflow behavior is observed inside the element this value is set on (e.g. "bounce" effects or refreshes), but no scroll chaining occurs to neighboring scrolling areas, e.g. underlying elements will not scroll.

none: No scroll chaining occurs to neighboring scrolling areas, and default scroll overflow behavior is prevented.

My guess is that whether history navigation falls under the category of "default scroll behaviour" is up to the particular browser / user-agent. The safest bet is probably to use none, unless there is some other "default scroll behaviour" that you need to retain.

Javascript

document.body.style.overscrollBehaviorX = "none";

CSS

body {
    overscroll-behavior-x: none;
}

Check the browser support table in the MDN link, and test on the browsers and devices you want to support.

starball
  • 20,030
  • 7
  • 43
  • 238