移动端滚动优化
#概述
iOS 的微信浏览器里实现滚动效果有几个问题:
- 通过
overflow: auto/scroll
实现的滚动会有很严重的卡顿感。 - 滚动到边界后继续上拉/下拉,会显示微信自带的遮罩(有时会遮盖住页面的原内容,感官上很不好)
第一个问题有两个解决办法:
- 设置
-webkit-overflow-scrolling: touch;
- 使用
better-scroll
等滚动类库 两种办法各有优缺点,-webkit-overflow-scrolling
有很多 bug,better-scroll
则在设置上有些坑,对嵌套循环支持也不好。
对第二个问题,设置个全局背景图/背景色可以盖住微信自带遮罩(但并不能阻止遮罩的存在,只是让人看不到了)
#-webkit-overflow-scrolling: touch;
一个很详细的 -webkit-overflow-scrolling: touch;
bug 说明文章:https://www.cnblogs.com/xiahj/p/8036419.html
另一个 bug 总结文章: http://www.cnblogs.com/chris-oil/p/6164966.html
目前注意事项主要是两个:
- 应用了这个属性、且设置了
overflow: auto/scroll
的元素,会建立一个新的堆叠上下文,且z-index
固定设为 0。 - 使用这个属性后,对于较长的滚动内容,很容易卡住。
#z-index(堆叠上下文)问题
根据这篇文章的解释:https://juejin.im/post/5b9ca817f265da0aeb70f477 使用这个属性后,元素会基于原生控件来渲染(性能更好,但会占用更多内存) 估计这也是它会建立新的层叠上下文的原因。
#堆叠上下文
CSS 中,元素的位置重叠时,要根据层级顺序决定谁显示在上面。 这方面的详细介绍可以看这两篇文章:https://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
简单的说:
- 同一个层叠上下文内的元素,谁后出现,谁显示在上面。
- 给元素设置
position: absolute/relative
会使其获得一个新的层叠上下文,它的所有子元素也包含进这个上下文。 - 两个层叠上下文之间,根据 z-index 确定谁显示在上面
- 层叠上下文里面还可以再创建一个层叠上下文,不过无论里面的 z-index 设的再高/再低,也无法抵消上级上下文的 z-index
#-webkit-overflow-scrolling: touch; 与层叠上下文
应用了 -webkit-overflow-scrolling: touch;
的元素会获得一个新的层叠上下文。 注意,并不是给哪个元素指定了这个属性,它就会获得它的效果。
- 这个属性和 font-size 一样,是会向下传递的
- 只有设置了 overflow / overflow-y 为 scroll 或 auto 的元素才会应用上对应的效果
获得层叠上下文的同时,z-index 会设为 0。 这个 z-index 是固定的,无法通过 CSS 修改。设为 auto 或一个数字都没用。 要调整它的显示层级,只能通过给其上级元素建立层叠上下文并设置 z-index 来实现。
#滚动卡住问题
目前观察,这个问题是滚动到顶部/底部继续触发微信浏览器遮罩显示后会出现。 因此有一个解决办法:在内容滚动到头部/尾部后,屏蔽后续滚动事件,这样遮罩就不会出现,也就不会卡住了。 相关资料:
- https://www.google.co.jp/search?hl=zh&q=微信浏览器+禁止上拉&safe=off
- https://github.com/sixwinds/blog/issues/17
- https://blog.csdn.net/weixin_39927850/article/details/79353228
- https://blog.csdn.net/bbnbf/article/details/51755401
#better-scroll 注意事项
使用 better-scroll 时,若不设置 click=true、tap=true 其中内容将不能点击
若要嵌套滚动,例如一个纵向滚动内容里出现了横向滚动的内容,要设置 eventPassthrough。 但问题是,使用 better-scroll 时有一个附加效果:保证不触发浏览器自带的回弹行为,也就避免了自带回弹会出现的滚动卡住等 bug。 但设置了 eventPassthrough 后,浏览器自带回弹就又出现了,滚动 bug 也会跟着出现。 详见:https://github.com/ustbhuangyi/better-scroll/issues/681