8

I would like to disable the swipe back animation totally on a SPA. That would allow me to use some swiping gestures within the SPA. At the moment on iOS you tend to also trigger the swipe back gesture when triggering certain gestures.

I have found this previous post about how to disable it: iOS 7 - is there a way to disable the swipe back and forward functionality in Safari?

They suggest following:

1) CSS only fix for Chrome/Firefox

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

2) JavaScript fix for Safari

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

The problem is that it does not deactivate the swipe back animation on iOS, it just replaces the place you get redirected to. Is there a way to also disable the swipe back animation on iOS? If there is no way to do it, does that mean you can't really use any swiping gestures if you build a PWA if you plan to have iOS customers?

Dominik
  • 397
  • 1
  • 3
  • 16
  • Swipe-back is built-into Safari on iOS. The action is the same as the Back button. So the answer is probably to disable back-button functionality on your site or for the specific pages where you want to disable that feature. – daddygames Apr 08 '19 at 13:26

3 Answers3

10

In iOS 13.4+ you can now preventDefault() on the "touchstart" start event to stop the navigation action.

Let's say we have a <div class="block-swipe-nav"> on the page that spans the entire width of the viewport and we want to prevent swipe navigation on that element.

const element = document.querySelector('.block-swipe-nav');

element.addEventListener('touchstart', (e) => {

    // is not near edge of view, exit
    if (e.pageX > 10 && e.pageX < window.innerWidth - 10) return;

    // prevent swipe to navigate gesture
    e.preventDefault();
});

I've written a short article on blocking swipe with some additional information.

Rik
  • 3,328
  • 1
  • 20
  • 23
  • Thanks for this. Have you had any issues with this only working part of the time? It seems like it blocks swiping back maybe 2/3 times, sometimes less. I'm guessing there's some timing issue going on here. – Lincoln Oct 12 '20 at 16:18
  • @Lincoln, it could be due to the `10` values. Maybe iOS also treats slightly larger X values as a navigational swipe. Do you have better success doubling these numbers? – Alex Peters Oct 23 '20 at 14:50
  • @Rik, great article. Especially useful within PWAs running on iOS, where the app is full-screen and swiping to navigate doesn’t necessarily make sense. – Alex Peters Oct 23 '20 at 14:54
  • No success. I ended up disabling browser history entirely on iOS/Safari devices (which is possible in my application since it's an SPA - single page app). – Lincoln Oct 24 '20 at 16:02
  • @Lincoln no it's working as intended. I did just read another comment where they state this doesn't work in fullscreen mode? – Rik Oct 26 '20 at 07:43
  • AHHHHH. This IS a fullscreen PWA, so that would seem to agree. That's entirely possibly the cause! I'll check into it. Thank you. – Lincoln Oct 26 '20 at 17:30
1

By default, there is no way to disable the swipe-back gesture. Also when you open the URL in a new tab, the back-button and swipe-left gesture will redirect you to the previous page.

There is one way when you haven't a back button: When you open a new tab in Safari and go to the URL there's is no URL to go back...

I found a small hack to make this possible in code. When Safari doesn't find the referrer anymore, the back button will disappear and the back-gesture doesn't work anymore :)

Opening the new page in a new tab is the only thing you have to do with something like the following code behind:

<a href="https://yoururl.com/path" target="_blank" onclick="handleClick()">Click here to open</a>
function handleClick() {
  setTimeout(function () {
    window.location.href = '?changeThePath';
  }, 100);
}

You need to change the original URL and, but the user doesn't see it because the new page is loaded in a new tab :)

Johnvh
  • 11
  • 1
0
document.body.addEventListener('click', function(evt) {
  const a = evt.target.closest('a:not([href^="#"])');
    
  if (!a) { return; }

  evt.preventDefault(); 
  history.replaceState({ }, '', a.href);
  location.reload();
});
miken32
  • 42,008
  • 16
  • 111
  • 154
NSD
  • 428
  • 4
  • 4