SO 上已经有多个关于溢出/橡皮筋滚动主题的问题,但是
- 它们都没有提供适用于 iOS 9.3.2 上所有情况的解决方案
- 他们都没有提供关于问题本身的广泛而完整的信息
这就是我创建这篇文章作为知识体系的原因。
问题:
在任何其他帖子中从未提及的是 iOS 溢出滚动实际上是一个两部分行为。
1。使用 overflow: auto/scroll
溢出内容滚动
这是具有 -webkit-overflow-scrolling: touch
的元素的众所周知且最需要的行为连续/动量滚动行为经过元素容器以平滑地减慢滚动内容。
当您以足够高的动量滚动元素的内容以使动量滚动超过滚动内容的长度时,就会发生这种情况。
有了这种行为,element.scrollTop
属性根据元素滚动位置而变化,小于 0 或大于最大滚动 (element.scrollHeight - element.offsetHeight
)。
2。 <body>
的溢出滚动
如果您尝试将任何已经处于其最小/最大滚动位置的元素滚动到比该位置更远的位置(顶部向上的元素或底部向下的元素),则会发生此行为。然后卷轴似乎“冒泡”到<body>
。标签和整个视口(viewport)滚动。
与上面相反的是 element.scrollTop
属性没有改变但是document.body.scrollTop
而是更改。
焦点锁定和行为切换(1.5秒延迟)
在此上下文中最令人恼火的是,上述两种类型之间的切换不会立即切换。
在您输入两者之一后,您无法将焦点切换到任何其他元素(可滚动元素、按钮、链接等),因此滚动行为也不会改变。
For instance: if you scroll a element already at its top position upwards you enter
overflow scrolling type 2
and the most natural reaction for a user is to then try to scroll back down. Because the focus is locked to the body scroll instead of going tooverflow scrolling type 1
it stays intype 2
and the whole body is scrolled downwards. The typical user then starts to arbitrarily starts to scroll up and down frequently without ever breaking out oftype 2
.
焦点的切换和滚动行为的改变只能在溢出动画结束并且元素静止不动(甚至比那长一点[大约 0.5 秒])之后发生。
thus going back to the previous example the correct reaction of the user would be to stop touching the screen for around 1s - 1.5s and then try to scroll downwards again.
最佳答案
解决方案:
类型 1:
防止元素本身溢出滚动的最基本解决方案是防止触摸事件默认。
document.body.addEventListener('touchmove', function(e) {
e.preventDefault();
});
然而,此方法会禁用浏览器的 native 动量滚动,因此不适用于大多数应用程序。然而,通过一些改进(只有在顶部向上滚动或底部向下滚动时才能防止......)这种方法解决了大多数问题。许多可能的实现可以在 this SO post 中找到.
类型 2:
然而,上面描述的方法并不能阻止 body 上的溢出滚动。
一个看似合理的可能解决方案是防止元素位于其顶部或底部位置,如 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>
上防止 body 移动的元素。 不过请注意这仍然没有完全停止type 2
避免发生,这就是为什么有时您无法滚动/聚焦任何元素,因为在后台 type2
它的焦点锁定仍在发生(再次,在您停止触摸屏幕片刻后它再次按预期工作)。
虽然这还远不是最佳解决方案,但它似乎是我们目前所能获得的最佳解决方案。
编辑:请注意,我不确定将 position: fixed
是否安全在 <body>
上元素。跟踪我创建的可能问题 following SO post .显然,创建一个包装元素作为 body 的子元素并将该元素设置为 position: fixed
可能会更好。以避免缩放问题。
编辑 2:定解
脚本iNoBounce创造奇迹。只需将其加载到页面,即可体验无弹跳的 Web 应用程序。到目前为止,我还没有发现这个解决方案有任何问题。
关于html - 防止 iOS 上的溢出/橡皮筋滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50004760/