防止iOS

时间:2016-06-02 08:17:26

标签: html ios css scroll overflow

关于SO上的溢出/橡皮圈滚动主题已有多个问题,但

  1. 它们都没有为iOS 9.3.2
  2. 上的所有案例提供解决方案
  3. 他们都没有提供有关问题本身的广泛而完整的信息
  4. 这就是我将这篇文章创建为知识体系的原因。

    问题:

    在任何其他帖子中从未提及的事情是iOS溢出滚动实际上是两部分行为。

    1。使用overflow: auto/scroll

    溢出滚动内容

    这是-webkit-overflow-scrolling: touch元素的众所周知且通常需要的行为,其中连续/动量滚动行为越过元素容器以平滑地减慢滚动内容。

    当您滚动元素的内容时,会出现动量高达足以让动量滚动超过滚动内容的长度的情况。

    通过此行为,element.scrollTop属性相应地更改为元素滚动位置并且小于0或大于最大滚动(element.scrollHeight - element.offsetHeight)。

    2。 <body>

    的溢出滚动

    如果您尝试滚动已经处于其最小/最大滚动位置的任何元素甚至超过该位置(顶部向上的元素或底部向下的元素),则会发生此行为。然后滚动似乎“冒泡”到<body>标签,并滚动整个视口。

    与上述相反,element.scrollTop属性不会更改,但document.body.scrollTop会更改。

    聚焦锁定和行为之间的切换(1.5秒延迟)

    在这种情况下最令人恼火的是,上述两种类型之间的切换不会立即切换。

    输入其中一个之后,您无法将焦点切换到任何其他元素(可滚动元素,按钮,链接......),因此滚动行为也不会改变。

      

    例如:如果您向上滚动已经位于其顶部位置的元素,则输入overflow scrolling type 2并且对用户最自然的反应是尝试向下滚动。因为焦点被锁定到身体滚动而不是overflow scrolling type 1,所以它停留在type 2并且整个身体向下滚动。然后,典型的用户开始任意开始频繁地向上和向下滚动,而不会突破type 2

    焦点切换以及滚动行为的改变只能在溢出动画结束且元素静止后(甚至比[0.5s]更长一些时间)发生。

      

    因此回到上一个例子,用户的正确反应是停止触摸屏幕约1s - 1.5s然后再尝试向下滚动。

3 个答案:

答案 0 :(得分:11)

解决方案:

类型1:

防止元素本身溢出滚动的最基本解决方案是防止触摸事件的默认值。

document.body.addEventListener('touchmove', function(e) { 
    e.preventDefault(); 
});

然而,此方法会禁用浏览器本机动量滚动,因此不适合大多数应用程序。然而,通过一些改进(仅防止在顶部向上滚动或在底部向下滚动,...),此方法可以解决大多数问题。许多可能的实现都可以在this SO post中找到。

类型2:

然而,通过上述方法不会阻止身体上的溢出滚动。

一个看似合理的可能解决方案是防止元素处于其顶部或底部位置,如mentioned question所述的最佳解决方案。

anElement.addEventListener('touchstart', function( event ){
    if( this.scrollTop === 0 ) {
        this.scrollTop += 1;
    } else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
        this.scrollTop -= 1;
    }
}

然而,这在iOS 9.3.2上无法可靠地运行。

然而position: fixed元素上设置<body>以防止身体移动。 但是请注意这仍然不能完全阻止type 2发生,这就是为什么有时你无法滚动/聚焦任何元素,因为在后台type2中它的焦点锁是仍在发生(再次,在你停止触摸屏幕片刻之后它再次按预期工作)。

虽然这仍然不是最佳解决方案,但它似乎是我们在演讲时能够获得的最佳解决方案。

修改:请注意,我不确定将position: fixed放在<body>元素上是否安全。要跟踪我创建的following SO post可能出现的问题。显然,最好创建一个包装元素作为body的子元素,并将该元素设置为position: fixed以避免缩放问题。

编辑2:明确的解决方案

脚本iNoBounce可以创造奇迹。只需将其加载到页面并体验无反弹的Web应用程序即可。到目前为止,我还没有发现这个解决方案有任何问题。

答案 1 :(得分:1)

我认为这个问题仍然相关,所以...

请注意在身体上使用position: fixed。它可能会产生奇怪的滚动冻结错误-实际上它仍然会“橡皮筋”,但您不会看到它。

请参阅:Div scrolling freezes sometimes if I use -webkit-overflow-scrolling

答案 2 :(得分:0)

一个不错的,简单的本地解决方案。不需要Javascript。 只需向您的孩子添加溢出滚动即可。为您的应用提供良好的原生“触感”

body{
    position: fixed;
}