iOS safari浏览器上overflow: scroll元素无法滚动bug深究

2018-09-15 admin

前情提要

在之前我写过一篇文章:iOS safari浏览器上overflow: scroll元素无法滑动bug解决方法整理,这篇文章写的是,当iOS safari浏览器上出现大于父容器的svg元素,想给父容器加上overflow: scroll实现内部滚动效果而失败的总结。但当时并没有意识到这个问题的实际原理,只是知道了safari给scroll元素加入了原生的scrollView块

bug原理

最近在做一个项目的时候,在safari上遇到了一个其他的bug,却让我意识到了这个问题的终极原因。

项目bug是这样的:我在用Nuxt做一个展示站点,需要使用锚链接在页面刚进入的时候跳转到某个位置。这里我本来使用的是router api提供的scrollBehavior方法,但这个方法在Nuxt上有局限性。我就把实现方式改为:进入页面后,动态计算不同锚点位置的scroll top再设置父元素的scroll位置。

在其他浏览器上都是ok的,但在safari上就出了问题:在页面刚进入时无法正确获取到元素的scroll top,小很多,只有页面加载完成之后才可以。

究其原因,是因为我在页面上放了很多张图片让其自行占位,而在页面刚加载时,其他浏览器会预先获取到图片的大小而给其一个占位,无论图片是否加载完成页面总高度固定的。而safari就不一样,图片没加载成功时高度是0

图片没加载成功时高度是0。哇长见识了。

这时回想到之前在safari上的那个scroll bug,在查阅相关资料后就可以得出结论了:

safari浏览器在渲染页面元素的时候,会预先走webkit浏览器的渲染流程:

  1. 构建DOM tree
  2. 构建CSS rule tree
  3. 根据DOM和CSS tree来构建render tree
  4. 根据render tree计算页面的layout
  5. render页面

注意在第三步和第四步的时候,safari浏览器在构建render tree的时候,会预先找到相应的overflow: scroll元素,在计算页面layout的时候,会计算父元素的高度与子元素的高度,若子元素高于父元素,则在render页面时为其建立一个原生的scrollView。

这个scrollView有什么用的?其实就是为了给其一个弹弹乐的效果(但确实用户体验不错)。

当子元素是某个媒体格式时,比如img、object(svg)等,safari在加载完成之前是不会在计算在layout之内的,也就是高度为0,则子元素的高度就一定小于父元素的高度,safari不会给父元素一个原生的scrollView。

解决方法

反其道而行之。当出现这种问题的时候,给子元素一个包裹元素,包裹元素设置一个min-height大于父元素的高度,让父元素有scrollView。当子元素加载完成时,将包裹元素撑开,父元素便可以自由滚动了。

原文链接:https://segmentfault.com/a/1190000016408566

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-40329.html

文章标题:iOS safari浏览器上overflow: scroll元素无法滚动bug深究

相关文章
React Native 用JavaScript编写原生ios应用
ReactNative 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App。而且React Native已经用于生产环境——Facebook Groups iOS 应用就是基于它开发的。 Re...
2015-11-12
js实现手机拍照上传功能
在前段时间的项目开发中,用到了拍照上传的地方,后来发现了最为简单的一种方法,现总结如下: <form id="form" method="post" action="http:&#x2...
2017-03-06
jQuery中DOM树操作之复制元素的方法
本文实例讲述了jQuery中DOM树操作之复制元素的方法。分享给大家供大家参考。具体分析如下: 复制元素 前面提到的操作包括:插人新创建的元素、将元素从文档中的一个位置移动 到另一个位置,以及通过新元素来包装已有的元素。可是,有时候也会用到...
2015-11-13
js实现文字向上轮播功能
话不多说,请看实现代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">...
2017-03-10
微信JSSDK上传图片
前不久微信公开了一些接口,其中有一个uploadImage接口用于上传图片,一般和chooseImage接口配合使用。先调用chooseImage接口让用户选择一张或者多张图片,用户选择完毕后微信会返回被选中图片的id,再把图片id传给up...
2017-03-29
jQuery给多个不同元素添加class样式的方法
本文实例讲述了jQuery给多个不同元素添加class样式的方法。分享给大家供大家参考。具体分析如下: jQuery可以通过addClass()方法给多个不同的html元素同时添加相同的class <!DOCTYPE html>...
2017-03-22
AngularJS 文件上传控件 ng-file-upload详解
网上可以找到的 AngularJS 的文件上传控件有两个: angular-file-upload:https://github.com/nervgh/angular-file-upload ng-file-upload:https://g...
2017-03-10
Javascript实现数组中的元素上下移动
交换数组可以实现元素上下移动了,这个效果我们在表格或以前排序算法中都会用到,下面来看一个JavaScript下实现交换数组元素上下移动例子 在写项目的时候,要实现一个数组记录上下移动的示例。写起来也没有没麻烦,无非是交换数组元素。最终实现代...
2017-05-02
详解使用vue-router进行页面切换时滚动条位置与滚动监听事件
按照正常的产品逻辑,我们在进行页面切换时滚动条应该是在页面顶部的,可是。。。在使用vue-router进行页面切换时,发现滚动条所处的位置被自动记录了下来,且在另一个组件内定义的滚动监听事件仍会运行,着实吃了一大惊。。。 说说我的破解方法:...
2017-03-13
js获取数组的最后一个元素
在js里面如何获取一个数组的最后一个元素呢?这里总结了两种方法,有需要的朋友可以看看。 (1)js内置pop方法 pop() 方法用于删除并返回数组的最后一个元素,注意这里在获取了数组的最后一个元素的同时也将原数组的最后一个元素给删除了。如...
2017-03-22
回到顶部