关于 SO 上的溢出/橡皮筋滚动主题已经有多个问题但是
- 它们都没有提供适用于 iOS 9.3.2 上所有情况的解决方案
- 他们都没有提供有关问题本身的广泛而完整的信息
这就是为什么我创建这篇文章作为知识体系的原因。
问题:
在任何其他帖子中从未提及的事情是 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.5 秒])之后发生。
因此回到前面的例子,用户的正确反应是停止触摸屏幕大约 1 秒到 1.5 秒,然后再次尝试向下滚动。
原文由 Aides 发布,翻译遵循 CC BY-SA 4.0 许可协议
解决方案:
类型 1:
防止元素本身溢出滚动的最基本解决方案是防止触摸事件默认。
但是,此方法会禁用浏览器的本机动量滚动,因此不适用于大多数应用程序。然而,通过一些改进(只有在顶部向上滚动或底部向下滚动时才能防止……)这种方法解决了大多数问题。在 此 SO 帖子 中可以找到许多可能的实现。
类型 2:
然而,上面描述的方法并不能阻止 body 上的溢出滚动。
一种似乎合理的可能解决方案是防止元素位于其顶部或底部位置,如 上述问题 的最佳解决方案所述。
然而,这在 iOS 9.3.2 上并不可靠。
然而,起作用 的是在
<body>
元素上设置position: fixed
--- 以防止身体移动。 _但是请注意_,这仍然没有完全阻止type 2
发生,这就是为什么有时你无法滚动/聚焦任何元素,因为在后台type2
其焦点锁定仍在发生(再次,在您停止触摸屏幕片刻后,它再次按预期工作)。虽然这还远不是最佳解决方案,但它似乎是我们目前所能获得的最佳解决方案。
编辑: 请注意,我不确定将
position: fixed
放在<body>
元素上是否安全。为了跟踪我在 SO post 之后 创建的可能问题。显然,最好创建一个包装元素作为 body 的子元素并将该元素设置为position: fixed
以避免缩放问题。编辑2:确定的解决方案
脚本 iNoBounce 创造 奇迹。只需将其加载到页面,即可体验无弹跳的 Web 应用程序。到目前为止,我还没有发现这个解决方案有任何问题。