andrei
andrei

Reputation: 8582

Stop chrome back/forward two finger swipe

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?

Upvotes: 53

Views: 37860

Answers (11)

P. Navarro
P. Navarro

Reputation: 115

Posting a non-CSS answer, which sometimes you don't have access to.

Run chromium / chrome with the disable-features=OverscrollHistoryNavigation :

# Run Chromium or Chrome with following flag
chromium --disable-features=OverscrollHistoryNavigation

Other gesture-related flags are usually recommended (such as the one that disables zooming via pinch, --disable-pinch), can be found here: https://niek.github.io/chrome-features/, which is a blog post recommended on the official docs (here, down bottom)

Upvotes: 0

Breck
Breck

Reputation: 2335

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

html, body {
  overscroll-behavior-x: none;
}

Upvotes: 123

nabrown
nabrown

Reputation: 836

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

Upvotes: 10

hjhlarsen
hjhlarsen

Reputation: 157

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 });

Upvotes: 1

CharlieM
CharlieM

Reputation: 658

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

Upvotes: 2

user3139574
user3139574

Reputation: 1169

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.

Upvotes: 8

Endoplasmic
Endoplasmic

Reputation: 59

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.

Upvotes: 0

Gabriel Doty
Gabriel Doty

Reputation: 1786

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));

Upvotes: 2

redgetan
redgetan

Reputation: 953

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();
  } 
});

Upvotes: 10

Niels Keurentjes
Niels Keurentjes

Reputation: 41958

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.

Upvotes: -4

roy riojas
roy riojas

Reputation: 2476

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

Upvotes: 0

Related Questions