16

Swiping from the left and right edges of my iPad's Safari browser, moves between the currently open web pages. Is there any way to prevent it?

I have tried to add touchstart and touchmove handlers on the edge of the page that stopPropagation and preventDefault, but they seem to have no effect, nor does touch-action CSS.

A similar question was asked in 2014 with replies to the negative: iOS 7 - is there a way to disable the swipe back and forward functionality in Safari?

Is there a workround now in 2018?

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
  • 4
    I wouldn't recommend doing this. Disabling essential navigation actions in a browser will confuse users. – Tamás Sengel May 03 '18 at 13:48
  • 6
    My app is a single page app, that lets users move cards around on the screen. What confuses users is that the whole page moves if they start trying to move a card that's near the side of the screen. Android Chrome solves this by only allowing navigational swipes on the chrome bar. – ᴇʟᴇvᴀтᴇ May 03 '18 at 13:55
  • 1
    The solution for this would be providing a so-called safe area for the cards in the center of the screen, where they can be freely moved. – Tamás Sengel May 03 '18 at 13:57
  • 2
    It's one workround, but not very intuitive / pleasant for users. I also have a split screen mode where a splitter can be dragged about and also docked on either side of the screen. That works nicely everywhere but iOS Safari. Once docked it can't be moved because the touch events around the edge of the screen are lost and any attempt to move it results in swiping between web pages instead. – ᴇʟᴇvᴀтᴇ May 03 '18 at 14:01

6 Answers6

11

In iOS 13.4+ you can now preventDefault on "touchstart"

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
  • 1
    In iOS 14 this will no longer prevent touch and drag down events anywhere within safari if browser is in fullscreen mode. It will always drag the browser out of fullscreen mode. – Johncl Oct 22 '20 at 08:29
3

Apple provided these guidelines after iOS9.

The guide lets you disable

  1. Scrolling

    function touchMove(event) {
      // Prevent scrolling on this element
      event.preventDefault();
      ...
    }
    
  2. Pinch and Zoom

    function gestureChange(event) {
      // Disable browser zoom
      event.preventDefault();
      ...
    }
    

You can identify a swipe gesture as follows:

  1. Begin gesture if you receive a touchstart event containing one target touch.
  2. Abort gesture if, at any time, you receive an event with >1 touches.
  3. Continue gesture if you receive a touchmove event mostly in the x-direction.
  4. Abort gesture if you receive a touchmove event mostly the y-direction.
  5. End gesture if you receive a touchend event.

The full guide is poster here.

Let me know if you need more help.

Nitin, Defuzed

Nitin K.
  • 39
  • 1
  • 3
    I already know how to interpret swipe gestures from touch events. The problem is that at the edge of the screen the browser behavior is different. It navigates between pages and I have found no way to prevent it. – ᴇʟᴇvᴀтᴇ May 03 '18 at 15:39
  • 4
    @ᴇʟᴇvᴀтᴇ ... and you probably won't find a way that's not very hacky. Seems like a native browser functionality that you as a web developer can't control... thats just how this particular browser works. Best you could do is to provide a warning message of the behavior to users. I think your hands are tied – zgood May 03 '18 at 15:47
  • 6
    Hmm, yes, it seems there's no way to prevent it. I wonder if Apple does this kind of thing purposely to make it harder for web apps to compete with App Store native apps. – ᴇʟᴇvᴀтᴇ May 03 '18 at 16:03
3

You can't, it's been a problem since the early days of iOS. They repeatedly drag their feet on powerful web app features, such as service workers and webgl.

The best you can do is what you should do for every browser, make the best experience you can using feature detection for every browser. Long gone are the days of making all sites look the same on every browser.

Use a sandwich if needed, allow side swipes on browsers that support it. There is no shame in disabling a small feature on a few browsers for the benefit of the rest of your users.

  • Not really feasible in case of games, charts or any advanced interaction that the user should be able to do anywhere on the screen. The main problem is that Apple and cie, do not view their browsers as anything else than a simple page viewer where the only activity of a user is to read text and check some pictures. – Kev Jan 13 '20 at 11:41
1

There appears to be no way to disable this functionality, so as a workround I've found that a deadzone of 24px on either side of the page seems to be enough to stop unintentional navigation.

Here is my CSS:

body {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 24px;
  right: 24px;
  background-color: #ccc;
}

Making the body position: fixed also stops Safari doing the annoying overscroll/bounce effect.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
0

Navigation on swipe gestures are possible if there is a navigation history. Swipe left is the "go back to the previous page in my navigation history".

So, if your app does not need a navigation history, which may be totally valid for a single screen game for example, then you can prevent the swipe issue by removing the navigation history.

For example, I have a single page application that uses only in-memory history, I don't synchronize with the browser (history / URL). So, the "swipes" have nowhere to go to and "fix" this problem.

That said, this is a work-around with its limitations that may not be good enough for your situation. (URL sharing is a basic thing in Internet)

It seems browsers vendors mission is to make web developers's life miserable with silly things like that.

Kev
  • 5,049
  • 5
  • 32
  • 53
  • This sounds interesting, but I don't completely understand how to implement it. Can you explain how to "remove the navigation history"? On my iPad the swipes go between the open tabs (which aren't under my control). – ᴇʟᴇvᴀтᴇ Dec 13 '19 at 15:58
  • Before I say anything, is your app online somewhere to check it out? – Kev Dec 13 '19 at 16:04
  • No, I never ended up putting out into the world. (Or, at least, not yet). – ᴇʟᴇvᴀтᴇ Dec 13 '19 at 16:07
  • 2
    I saw your question from 2018..,referring to another of 2014. Well it's almost 2020 and still a problem. Without the details of your app situation, I can only talk about mine. We tested this in iphone 5S / ipad, with ios 12, and 13. Our SPA is a react app and I have removed the synchronization of the navigation with the browser history. I made my own router so I won't explain it here. But if you want an example, it would be the equivalent of using React Router "Memory Router". https://reacttraining.com/react-router/web/api/MemoryRouter – Kev Dec 13 '19 at 16:14
  • 1
    Unfortunately, you cannot wipe the browser history. You can navigate through your app without adding to history, but if the user came to your site through another one, there will always be history. One option is to open your app in a popup if the history object if too long when arriving in your app. – pieroxy Apr 22 '20 at 06:44
  • @pieroxy You are right. In the end it's just a bunch of workarounds and hacks on top of one another due to the narrow view of browser vendors. The real solution would be for browsers dev to think that in 2020, we ship more than text and cat images. – Kev Apr 22 '20 at 13:40
  • A better way to eliminate navigation history is to ensure there is no history to begin with. You can do that by ensuring all of your website's links to the actual game page open the page in a new tab by using target="_blank". Other websites can still link directly to the game page but they will often use target="_blank" too (since it is an external link), and you may be able live with those cases where they don't. – Bob Arlof May 01 '20 at 15:47
-1

Try this in the <body> tag:

onload='ontouchmove()="return(function(event) { event.preventDefault(); event.stopPropagation(); return(false); } );"'

I imagine there might be some side effects by not letting IOS know about moving but for SPW they're probably slight.

Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73