在移动Safari上禁用滚动和弹跳效果。

148
我正在开发一个基于浏览器的应用程序,目前我正在为iPad的移动Safari浏览器进行开发和样式设计。
我正在寻找两个解决方案:如何禁用不需要垂直滚动的页面?以及如何禁用弹性反弹效果?

请参考以下答案,这是我使用并且最新的(https://dev59.com/ilUL5IYBdhLWcg3wKlR1#51176339)。 - frage
23个回答

159

这个答案已经过时了,除非你正在为一个非常老的iOS设备开发...请查看其他解决方案


2011年的回答:对于在iOS Safari中运行的Web/HTML应用程序,您需要类似以下的东西

document.ontouchmove = function(event){
    event.preventDefault();
}

针对iOS 5,您可能需要考虑以下内容:document.ontouchmove和iOS 5上的滚动

2014年9月更新: 您可以在此处找到更全面的方法:https://github.com/luster-io/prevent-overscroll。对于其中的许多有用的 Web 应用程序建议,请参见 http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

2016年3月更新:上面的链接已经失效 - 可以查看 https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist.html来获取归档版本。感谢@falsarella指出这一点。


1
我在iOS Safari内运行的Web应用程序中尝试禁用ontouchmove事件,但如果小心操作,仍然可以看到反弹效果。(iOS 5) - Nilesh
7
禁用反弹效果怎么样? - Yuval A.
8
这种方法的问题在于,您dom中可滚动的div将不再滚动。根据您的dom设置,有解决方法。 - huesforalice
4
这里有很多人在询问如何在使用此功能时滚动div,为了使这些div可滚动,请添加 onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); }。它会阻止事件传播到body上,但是body仍然不会反弹。编辑:这是在假定您设置了 $ ('div').on('touchmove', ...onTouchMove); 的情况下。 - Matt Kenefick
1
@OskarAustegard,最后一个链接打不开,但我在Web Archive上找到了内容:http://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist.html - falsarella
显示剩余12条评论

127

你也可以将 body/html 的位置更改为 fixed:

body,
html {
  position: fixed;
}

2
这在iPad iOS 8.2 Safari上实际上非常有效,不再有反弹效果了。 - Akseli Palén
3
到目前为止我看到的最好的做法 - hildende
9
如果您想使用position:absolute并将所有边框设置为0(以制作全屏div),则此方法无法正常工作 - 整个文档会变得微不足道。 - riv
4
当我使用此功能并将焦点放在输入框上时,页面会跳回页面顶部。您知道有没有解决方法? - Julie
3
在body和html中都添加width: 100%; height: 100%有所帮助。 - Tim
显示剩余8条评论

83

为了防止在现代移动浏览器中滚动,您需要添加passive: false。在找到这个解决方案之前,我一直在苦苦寻找使其正常工作的方法。我只在互联网上的一个地方发现过这个提及。

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault);
}


7
没有 { passive: false } 它肯定不起作用!!!欢迎来到 StackOverflow 啊,伙计。 - Ser
2
非常感谢您提供这个解决方案! - Paul Z.
6
这是正确答案。在Chrome 54之后,touchmove默认为true,这意味着preventDefault调用将被忽略。因此,您必须传递{passive:false},以便preventDefault调用不会被忽略。您可以在此处查看解释:https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener。 - derickito
2
你正在JS中声明函数-但是如何调用该函数以使其按照建议的方式工作在一个元素上? - ikwyl6
10
如果您想禁用所有类型的滚动,则可以使用这个方法。但是如果我只想禁用页面主体的滚动,并保留对具有“overflow-y:scroll”属性的元素进行滚动的可能性呢?例如,在模态框中,视图高度比页面主体还要高。 - Calsal
正确,这个解决方案确实停止了橡皮筋效应,但也会在内容溢出时禁用滚动条。有人解决了这个问题吗? - Mattijs

8

CSS overscroll-behavior 在 iOS 16 中已得到支持。如果您的目标设备是 > iOS 16,则需将以下 CSS 添加到 html 根元素中以防止弹性反弹效果。

html {
  overscroll-behavior: none;
}

请注意,所提供的解决方案仅在内容大于视口时禁用弹性反弹效果。
如果您还想在iOS设备上完全禁用主页面的滚动,请使用
html body {
   overflow: hidden;
}

7

1
连同在<body>上使用overflow:hidden,这仍然是最好的解决方案。但是当打开键盘或滑动屏幕底部时,它将不再起作用。 - Fabian von Ellerts
尝试输入 onfocus 移除 overflow。 - user956584

7
您可以使用以下jQuery代码片段来实现这个功能:
$(document).bind(
      'touchmove',
          function(e) {
            e.preventDefault();
          }
);

这将阻止页面的垂直滚动,以及任何反弹效果。

13
这不是Javascript,而是jQuery。你应该提及它,因为并不是每个人都在使用这个框架。 - inta
如何停止水平弹跳或滚动。 - fidel castro
水平滚动条可以通过CSS轻松禁用,只需将overflow-x:hidden; 应用于主容器即可。但我注意到在最新版本的Safari中,您无法禁用弹跳效果。这是移动设备浏览器的本地功能。 - Alessandro Incarnati
6
只是说,这实际上是 JavaScript。只是它不是纯 JavaScript。 - Ben Lorantfy

4

如何在iPad Safari中禁用滚动和弹跳效果:

   document.addEventListener("touchmove", function (e) {
        e.preventDefault();
    }, { passive: false });

如果文档中有画布标签,有时它会影响画布内对象的可用性(例如:对象的移动);因此,请添加以下代码以进行修复。

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });

4
我知道这与主题稍有偏差,但我一直在使用Swiffy将Flash转换为交互式HTML5游戏,并遇到了相同的滚动问题,但没有找到有效的解决方案。
我的问题是Swiffy舞台占据了整个屏幕,因此一旦加载完成,文档上的触摸移动事件就不会被触发。
如果我尝试将同样的事件添加到Swiffy容器中,它会在舞台加载完成后被替换掉。
最后,我通过将触摸移动事件应用于舞台内的每个DIV来解决了这个问题(非常凌乱)。由于这些div也在不断变化,我需要不断地检查它们。
这是我的解决方案,看起来效果很好。希望对其他正在寻找与我相同解决方案的人有所帮助。
var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}

这将禁用iPad上的整个滚动。 - fidel castro

3

对于我来说,上述解决方案都不适用。这是我的解决方法。

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }

我会这样做: .the_element_that_you_want_to_have_scrolling{ scrolling: touch; } - Roy Segall
你的答案对于html,body有效,但是我无法让“the_element_that_you_want_to_have_scrolling”滚动。这个元素嵌套在一些位于body下面的div中。我想知道我想要滚动的这个嵌套div的任何典型元素标签是否有影响?我已经设置了position: relative。 - ikwyl6
这个固定位置的解决方案对我很有效,而JS解决方案则不行,因为它会破坏我的舞台滚动(粘性页眉和页脚)。在我的舞台区域使用overflow-y: auto允许滚动,因此我不需要那个webkit指令。 - Mattijs

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接