44

I want to disable the two finger swipe that causes Chrome going back or forward. I have a website where the user might lose progress on his work if he doesn't specifically saves.

I have tried using window.onbeforeunload but that doesn't seem to work if I have hashes in the url (back forward would change between www.example.com/work/#step1#unsaved www.example.com/work/#step0) and the event doesn't seem to trigger.

I was about to switch to another solution but today I noticed that in Google Docs it's completely disabled. How did they achieve that?

andrei
  • 8,252
  • 14
  • 51
  • 66

10 Answers10

102

The top answer from: Disable Chrome two fingers back/forward swipe worked for me. In your CSS file:

html, body {
  overscroll-behavior-x: none;
}
Sumit
  • 2,242
  • 1
  • 24
  • 37
Breck
  • 2,075
  • 1
  • 13
  • 10
  • 10
    If this doesn't work for you, try specifying `overscroll-behavior-x` on the `html` element. – Matt Sanders Oct 01 '19 at 23:47
  • Thank you @Matt Sanders, this is great, that gesture is sometimes surprisingly easy to trigger with the horizontal scroll – Alex Sorokoletov Jul 19 '20 at 03:51
  • 1
    Semi off topic, but it's worth noting that this also works on other elements. Which is especially useful if you want to keep the two finger swipe for the entire page, but want to disable it for specific sections that have horizontal scroll. – Senne Sep 28 '21 at 13:12
  • 1
    Save my day,!!! I was finding javascript solution, detecting Swipe left right and then preventDefault, but this is quite easy .... Thank – Shurvir Mori Jun 09 '22 at 06:15
  • If you only want this in some elements, say ``, you want to `addEventListener('mouseenter'/'mouseleave'` and attach/remove the class on `` – Noble Dinasaur Nov 01 '22 at 18:05
  • does the trick on chrome – Ivan Hanák Apr 04 '23 at 14:41
10

Make the specific page open in a new tab/window by default (by putting target="_blank"> in hyperlink). That way there'll be no previous page to go back to.

Or prevent Horizontal Scrolling by default. To do that, you can use jquery.mousewheel to do:

$(document).on("mousewheel",function(event,delta){ 
  // prevent horizontal scrolling
  if (event.originalEvent.wheelDeltaX !== 0) {
    event.preventDefault();
  } 
});
redgetan
  • 943
  • 1
  • 8
  • 12
  • It's better to use "event.stopPropagation()" – sheerun Oct 16 '15 at 12:26
  • 2
    @sheerun No it's not. stopPropagation kills the event which might lead to unexpected behavior and bugs in third party code that relies on these events to be fired. Always prefer preventDefault. Also, preventDefault doesn't seem to be working anymore for this case in Chrome 59.0.3071.115 (and neither does stopPropagation). Does anyone have a solution to that? – Jesse Jul 03 '17 at 16:21
  • Yep, just got bit by this on Chrome 60 D: – Dogoku Sep 09 '17 at 15:32
10

Assuming you have a horizontal-scrolling element, adding overscroll-behavior-x: contain; is the easiest way prevent the scroll action from spilling out into the page and causing the navigation.

https://dev.to/danburzo/css-micro-tip-prevent-history-navigation-on-horizontally-scrolling-elements-3iil

https://caniuse.com/#feat=css-overscroll-behavior

extempl
  • 2,987
  • 1
  • 26
  • 38
nabrown
  • 827
  • 10
  • 15
  • This does not seem to prevent the back navigation from happening while horizontally scrolling on Chrome in Windows. Edit: Apparently is does work when the property is on the `html` tag and not the scrollable container. – Matej Kormuth Aug 21 '21 at 22:00
8

Disable or replace swipe gestures for Google Chrome 61

The question that leads me here was marked "duplicate" and closed to answers. I believe this answer is better suited for the "duplicated" question, however, I feel this answer could possibly save time for someone landing on either question.

Better question: Disable navigation swipe on Chrome browser in javascript

This Google developers article helped me to allow the e.preventDefault() to work and prevent swipe gestures as of Chrome 61.

https://developers.google.com/web/updates/2017/01/scrolling-intervention

givanse's answer to the following was the code that I used to write my own swipe event handlers:

Detect a finger swipe through JavaScript on the iPhone and Android

In summary, the following two events are used to implement the swipe gestures:

handleTouchStart (e) {
  ...
},
handleTouchMove (e) {
  ...
  e.preventDefault()
}

As of Chrome 56, the default behavior is to make the event listeners passive and thus disable the ability to prevent Chrome's swipe gestures. To override this behavior, event listeners can be added as follows:

document.addEventListener(
  'touchstart',
  this.handleTouchStart,
  {passive: false}
)
document.addEventListener(
  'touchmove',
  this.handleTouchMove,
  {passive: false}
)

By passing the {passive: false} object as the third parameter to the addEventListener method, the listener is registered as active and can stop Chrome's default behavior with the e.preventDefault() event method.

Salomon Zhang
  • 1,553
  • 3
  • 23
  • 41
user3139574
  • 1,119
  • 10
  • 6
2

Building on both the previous answers given by @roy riojas and @redgetan - I combined their answers to allow for this to be dynamic and prevent both forward and backwards - again - per @roy's comments - you must know the class of your element, and for this implementation - the class of the nested element that is actually being scrolled

(function ($) {
  $(document).on('mousewheel', function(e) { 
    var $target = $(e.target).closest('.scrollable-h');
    var scroll = $target.scrollLeft();
    var maxScroll = $target.find('.scrollable-h-content').width() - $target.width();

    if(scroll <= 0) {
      if(scroll <= 0 && e.originalEvent.wheelDeltaX >= 0) {
        e.preventDefault();
      }
    }
    if(scroll >= maxScroll) {
      if (scroll >1 && e.originalEvent.wheelDeltaX <= 0) {
        e.preventDefault();
      }
    }
});}(jQuery));
Gabriel Doty
  • 1,686
  • 1
  • 11
  • 7
2

I've been working on something similar where I want to override the forward/backward history swiping gesture. Depending on what your swipe area is you can tweak the selector as follows:

html { touch-action:none; }

This is the associated documentation that gives you all the properties to all touch actions like panning or zooming features built into the browser.

https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

CharlieM
  • 658
  • 6
  • 9
1

You can disable back/forward with this code:

document.addEventListener("wheel", function(event) {
    event.preventDefault();
}, { passive: false });

Note that adding { passive: false } is essential, at least in Chrome. If you only want to disable back/forward in certain areas you can use code like this (assuming you're using jquery and you add the class disable-back-forward to the sections where you want to disable back/forward):

document.addEventListener("wheel", function(event) {
    if ($(event.target).closest('.disable-back-forward').length)
        event.preventDefault();
}, { passive: false });
hjhlarsen
  • 147
  • 9
0

Hi this worked for me on chrome but not for the entire page, but for places where I have scrollable content.

In Google Docs (Spreadsheets) it seems to be working because they don't have a back page to go. If you navigate to another URL (manually) it will not prevent you from navigating back.

$(document).on('mousewheel', function(e) { 
  var $target = $(e.target).closest('.scrollable-h');
  if ($target.scrollLeft () <= 4) {
    $target.scrollLeft(5);
    return false;
  }
});

One thing to keep in mind is that the code above is making two assumptions:

  1. your element with horizontal scrollable content has a class scrollable-h
  2. If checks if the scrollLeft if bigger less than 4px and then just make it scroll to 5px returning false effectively cancel the back gesture

Important: - This only prevents the back swipe gesture, when is done fast, if you do it very slow it will still trigger sometimes.

  • Also this does not prevent the forward swipe gesture, but it could also be done by checking if the element has reached the maximum scrollLeft. If that is the case then move it 20px back and return false to prevent the event from happening... It is up to you to add this use case if it happens to make sense to you.

You can take a look to a proof of concept here. http://jsfiddle.net/royriojas/JVA6m/#base

roy riojas
  • 2,406
  • 1
  • 28
  • 30
  • 1
    So how do you prevent the bounce? It seems the only way to detect whether we are at the edge is after the scroll occurse, and not before – Kevin Newman Feb 15 '18 at 19:55
  • 1
    @KevinNewman I want to thank you so much. I've spent a lot of time trying to figure out why the `preventDefault` on the `wheel` event didn't work for me. But then I noticed the word "bounce" in your comment and suddenly realized. I used the `_.throttle` on my event handler which was breaking the `preventDefault`. This is not related to the original question, but anyway thanks! – jastkand Jul 09 '19 at 08:02
0

I was able to disable it by typing chrome://flags in the address bar and heading down to "Overscroll history navigation" and setting it to "Disabled" from the dropdown.

Endoplasmic
  • 59
  • 1
  • 4
-4

You're looking at the problem at the wrong level. OnBeforeUnload is simply not triggered because there is nothing being unloaded from the browsers perspective. Therefore you have, quite bluntly, implemented the wrong mechanism for versioning - fragments are for page states, not document states as you are using it now.

If you insist on maintaining state through hash fragments you need to use another mechanism to guard against page state changing. Since all current browsers support LocalStorage I'd use that. And well, while at it, put all the document state data there instead of in the URL, since that is how Google Docs does it and that is why they don't have this issue.

Niels Keurentjes
  • 41,402
  • 9
  • 98
  • 136
  • 1
    I already discovered that `onbeforeunload` doesn't work "I have tried using window.onbeforeunload but that doesn't seem to work " – andrei Apr 13 '13 at 09:08
  • 1
    I think you misunderstood the question. If the user is horizontal scrolling in div, for example, sometimes they reach the end and then Chrome will trigger a page back or page forward action. This is orthogonal to the url hash. Google Docs somehow disables this. – Breck May 10 '19 at 06:25