转载请注明英文原文及译文出处

原文地址:Issues with position fixed & scrolling on iOS
原文作者:Remy Sharp
译文地址:移动端 fixed 和 scroll 问题
译文作者:鎏金圣手火麒麟

最近在做iOS端的H5页面时,遇到了一个定位问题:
1、position: fixed 元素在页面滚动时属性值变为absolute,在页面停止滚动瞬间,才恢复fixed;
2、当使用 fixed 定位的元素,存在于进行滚动的容器元素内时,拖动容器元素会使出现闪动问题。

在寻求解决方案的过程中,看到了这一篇文章,对这个问题的原因解释得不错,故翻译过来,供大家参考。
翻译的过程中,对原文小标题做了修改,方便大家阅读。
翻译不对的地方,也可以在评论中帮忙指出,谢谢。

以下是译文:

随着iOS 5的发布,fixed 定位据说将会支持移动端Safari。

当然,这个说法并不一定是真的,因为在下文中我将给大家展示各种各样的bug。

顺带一提,在iOS 5的测试阶段,我已经向苹果的bug报告工具上传了一些bug,但天知道这个工具是怎么运行的,所以我不知道这些问题的编号(此处有争议,原文:the issue numbers)。

更新:基于 Corey Duston 指出关于 position fixed 的更多bug,我已经添加了 "scrolling == unusable position:fixed element"模块。

position:fixed, who cares?

我认为对于一个好的app而言,不一定非要使用到 fixed 定位。但是,我也注意到有越来越多的 iOS app 开始使用 fixed 定位的工具栏,比如 mini-MobileSafaris,苹果应用商店的原生 Facebook app 和 Instagram。



AppStore via @devongovett, Facebook via @9eggs

问题

我已经创建了一些示例页面,方便大家自行查看。(以下视频来自油管,需要梯子)

问题1:抖动

如果你将 position: fixed 用任何正常的方式添加到桌面级页面中,你就会在滑动页面的时候,看到一定程度的抖动问题。

视频链接:https://www.youtube.com/embed/yps8Ea5GO4I?fs=1&feature=oembed

请注意这是在模拟器上出现了该bug,但我同样在 iPhone 真机上捕获了相同的bug。
模拟地址:http://jsbin.com/3/ixewok/6/

问题2:滑动时无法更新数据

眼尖的小伙伴可能已经发现了视频中的某些值发生了变化。我监控了 window.scrollTopwindow.pageYOffset(还有另一个值将会在下文提到)。你会注意到这两个值只有在页面滑动完全停止后才会发生变化。

当你想要在通讯录APP中模拟碰撞和分流式头部目录时,这就是个问题了。
(这句翻译的不好,原文:This is a problem if you want to monitor the page position to simulate effects like the bumping and shunting of category headings like you might see in the address book app.)

问题3:位置漂移

如果页面被放大到最大倍数,比如在 iOS 上,当用户将页面从纵向旋转到横向后,再进行任何比例超过1的缩放操作(比例放大),定位元素就会向上漂移。(我曾在其他网站见过元素彻底漂移出视窗的情况)

视频链接:https://www.youtube.com/embed/YIOdPf7jqK4?fs=1&feature=oembed
模拟地址:http://jsbin.com/3/ixewok/6/

问题4:获取焦点后跳跃

如果在 fixed 定位的元素中存在一个可以获取焦点的元素,比如 input 元素,这就有可能导致整个 fixed 元素跳到其他地方。这种情况只会在用户滑动页面的时候出现(如果这正是你想要的效果,那当我没说 XD)。

视频地址:https://www.youtube.com/embed/lrnvZDwgJRc?rel=0
模拟地址:http://jsbin.com/3/ixewok/8/

问题5:Scrolling == 无法使用的 position: fixed 元素

Corey Dutson指出还有另一个与 fixed 有关的bug。尽管在他的示例中滚动是通过JavaScript来实现,但核心问题是:如果页面是由脚本控制移动,那么在移动之后,fixed 定位的元素将不可使用。

从截屏中我已经做了记录,你可以通过iWebInspector看到,尽管 MobileSafari 已经在位置上渲染了 fixed 定位的元素,但它实际上并不在应该在的位置。当你再次触碰和移动页面时,真正的元素才会保持在正确的位置上。

视频地址:https://www.youtube.com/embed/R2MzdeJSCKw?fs=1&feature=oembed
模拟地址:http://jsbin.com/3/ixewok/13/

尽管我还没有找到这个bug的解决办法,并且我觉得可能这是 MobileSafari 自身的渲染问题,不过我还是会继续看看是否有办法解决。

解决抖动

随着 iOS 5 的发布,MobileSafari 同样支持了 -webkit-overflow-scrolling: touch。这实际上是用于页面内容的行内块元素(这句不知如何翻译:I mean inline with respect to the document)。

如果我在前文的示例中改变 css,并且设置 html、body、内容块的高度为100%,然后将 scrolling touch 属性应用到内容上,那么抖动就会消失了。然而,这并不能彻底解决问题。

有个巧妙的办法是这样的:确保使用 fixed 定位的元素不是一个“移动画布”。这个示例展示了一个 fixed 元素放置在一个滚动元素的上方,但在dom结构中,它并不是滚动元素的子级。

所以当我尝试将这个办法用在 body 元素上时,抖动问题还是存在,因为 fixed 定位元素仍然位于滚动元素内。

视频地址:https://www.youtube.com/embed/suXz5dKtlcA?rel=0

我同样在真机上捕获了这个问题:点击这里

模拟地址:http://jsbin.com/3/ixewok/10/

滚动位置更新

再来一次,仔细的小伙伴应该也注意到了某些值又发生了改变。请注意,由于我已经更改了CSS,因此 body 不再滚动,所以左右的 0 值分别对应 window.scrollTopwindow.pageYOffset。当窗口不可滑动时,内容块处于溢出状态,值也就不会改变。

但是,content.scrollX 的值仍在变化——但这不是默认的。

首先,你需要添加触摸事件,用来在用户滑动(或者触摸)时更新该值,所以在 JavaScript 中我可以添加:

content.ontouchstart = function() {};

touch 事件会发生在 start, end, move三个阶段,并且只需要一个值集(翻译的不好:a value set)。
(请注意,我并没有尝试直接将其设置为 true——这可能也能起作用)。

然而,这依然是不完美的。你可以在上面的视频中看到,值只会在我触摸的时候更新。当我的手指离开屏幕,让页面惯性滚动时,值就不会更新了。

我仍会继续尝试有没有可能获取该值(无奈……)

总结 / TL;DR

1、不要在滚动元素内部使用 position: fixed,否则它会出现抖动bug并且看起来很糟糕(我曾见过比视频中抖动得更疯狂的情况)。
2、确保使用 -webkit-overflow-scrolling: touch
3、如果你想要获取 scroll 的相关值,请确保你在滚动元素上添加了 touch 的监听事件。

同时,请在其他移动端浏览器也这么处理,不要只对苹果做这些处理。苹果对于 position: fixed 虎头蛇尾的做法真让人头疼,这作风跟巨硬真像。

Posted 24-May 2012

Issues with position fixed & scroll(移动端 fixed 和 scroll 问题)的更多相关文章

  1. web移动端fixed布局和input等表单的爱恨情仇 - 终极BUG,完美解决

    [问题]移动端开发,ios下当fixed属性和输入框input(这里不限于input,只要可以调用移动端输入法的都包括,如:textarea.HTML5中contenteditable等),同时存在的 ...

  2. 【转载】Web移动端Fixed布局的解决方案

    特别声明:本文转载于EFE的<Web移动端Fixed布局的解决方案>.如需转载,烦请注明原文出处:http://efe.baidu.com/blog/mobile-fixed-layout ...

  3. web移动端Fixed在Input获取焦点时ios下产生的BUG及处理

    1.现象 可以看到下面两张图,图1搜索框为fixed固定在顶部,滚动没有任何问题. 图2当光标进入搜索框时,ios自作聪明的把光标定位到中间,并且fixed属性被自动修改成了absolute.此时注意 ...

  4. position 的值absolute、fixed、relative和static的定位原点是什么

    position 的值absolute.fixed.relative和static的定位原点是什么 absolute 成绝对定位的元素,相对于值不为static的第一个父元素进行定位,也可以理解为离自 ...

  5. 微软BI 之SSIS 系列 - 平面文件格式的区别(Delimited,Fixed width,Ragged Right, Fixed width ...)

    开篇介绍 SSIS 中处理文件,一般在描述输出平面文件格式的时候通常会出现以下几种选项: Delimited - 默认输出列使用逗号分隔,也可以选择其它的诸如 | ,或者 Tab 等. Fixed W ...

  6. Web移动端Fixed布局的解决方案

    移动端业务开发,iOS 下经常会有 fixed 元素和输入框(input 元素)同时存在的情况. 但是 fixed 元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题. 这篇文章里就提供一个简单的有 ...

  7. [转] Web移动端Fixed布局的解决方案

    移动端业务开发,iOS 下经常会有 fixed 元素和输入框(input 元素)同时存在的情况. 但是 fixed 元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题. 这篇文章里就提供一个简单的有 ...

  8. 八、Web移动端Fixed布局的解决方案

    移动端业务开发,iOS 下经常会有 fixed 元素和输入框(input 元素)同时存在的情况. 但是 fixed 元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题. 这篇文章里就提供一个简单的有 ...

  9. 移动端fixed兼容问题

    最近做移动端页面,有个需求类似下图 底部导航用fixed定位时在部分iOS版本中会有问题: 1.上滑是底部会跟着滑动,手指松开时才会又回到底部 2.软键盘唤起的情况下,也会出现许多莫名其妙的问题 网上 ...

随机推荐

  1. k8s-ingress部署测试以及深入理解

    1.ingress 部署有两种方式.本次采用DaemonSet部署. apiVersion: v1 kind: Namespace metadata: name: ingress-nginx --- ...

  2. (第三章)TF框架之实现验证码识别

    这里实现一个用神经网络(卷积神经网络也可以)实现验证码识别的小案例,主要记录本人做这个案例的流程,不会像之前那么详细,主要用作个人记录用... 这里是验证码的四个字母,被one-hot编码后形成的四个 ...

  3. SQL Server的Linked Servers(链接)

    我们在使用SQL Server时,有时会有这种需求,需要从一个SQL Server服务器A中,查询另一个SQL Server服务器B中的表,然后将SQL Server服务器A中的表和SQL Serve ...

  4. .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式

    .Net Core 同 Asp.Net MVC一样有几种过滤器,这里不再赘述每个过滤器的执行顺序与作用. 在实际项目开发过程中,统一API返回值格式对前端或第三方调用将是非常必要的,在.NetCore ...

  5. MRS IoTDB时序数据库的总体架构设计与实现

    MRS IoTDB时序数据库的总体架构设计与实现 MRS IoTDB是华为FusionInsight MRS大数据套件最新推出的时序数据库产品,其领先的设计理念在时序数据库领域展现出越来越强大的竞争力 ...

  6. U8g2库的使用

    一.硬件介绍: 由于笔者这里只有0.96寸的OLED屏幕,那就讲讲最常用的0.96寸OLED屏幕吧. OLED介绍: OLED,即有机发光二极管( Organic Light Emitting Dio ...

  7. ArcMap操作随记(2)

    1.空间校正 变换-仿射 仅发生偏移 橡皮页变化 形状改变 变换-投影 旋转,改变角度 变换-相似 改变大小.形状不变 2.计算行列号 Int(([POINT_Y]-1273.143242)/30)+ ...

  8. bash shell 快捷键

     Bash Shell 快捷键: Ctrl + a - 跳到行首      Ctrl + e - 跳到行尾     Ctrl + k - 从光标处删除到行尾     Ctrl + l - 清屏,类似  ...

  9. linux下oracle数据库的启动

    linux下oracle数据库的启动 一.切换oracle用户 命令:su - oracle 二.运行sqlplus命令,进入sqlplus环境 命令:sqlplus /nolog (nolog参数表 ...

  10. [Java编程思想] 第二章 一切都是对象

    第二章 一切都是对象 2.1 用引用操纵对象   创建一个String引用: String s;   这里所创建的只是引用,并不是对象.   创建一个引用的同时便初始化: String s = &qu ...