admin管理员组

文章数量:1180551

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?

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?

Share Improve this question asked May 3, 2018 at 13:35 ᴇʟᴇvᴀтᴇᴇʟᴇvᴀтᴇ 12.8k5 gold badges45 silver badges68 bronze badges 4
  • 4 I wouldn't recommend doing this. Disabling essential navigation actions in a browser will confuse users. – user3151675 Commented May 3, 2018 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ᴀтᴇ Commented May 3, 2018 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. – user3151675 Commented May 3, 2018 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ᴀтᴇ Commented May 3, 2018 at 14:01
Add a comment  | 

7 Answers 7

Reset to default 10

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.

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.

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

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.

I found that I could prevent the left or right slide by popping up a question (confirm dialog) - similar to when you would want to prevent a user from leaving a half entered form. Once you have asked them if slide is ok, its up to the user.

<script type="text/javascript" language="javascript">
    //console.log('init');
    whenReady(function () {
        //console.log('ready')
        //alert('ready')
        document.addEventListener('touchstart', function (e) {
            //console.log('check to prevent drag right for back on ios');
            // is not near edge of view, exit
            if (e.pageX > 25 && e.pageX < window.innerWidth - 25) {
                //console.log('dont prevent drag right for back on ios now');
                return;
            }
            // prevent swipe to navigate gesture
            //console.log(' prevent drag right for back on ios now');
            if(window.AllowSlide) return true;
            if(!confirm('You may not want to side left or right, as you might loose some of your answers. Ok to slide?')){
                e.preventDefault();
                e.stopImmediatePropagation();
                e.stopPropagation(); 
                return false;
            }else{
                window.AllowSlide=true;
            }
        });
    });
</script>

Here is an example of the dirty checker code:

window.onbeforeunload = function () {if (window.checkForPageDirty && stopIfDirty()) {}});

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.

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.

本文标签: javascriptPrevent swiping between web pages in iPad SafariStack Overflow