html移动端兼容性的调研

本文属于随性畅谈的文章,可以跳到需要的部分阅读。

兼容性不可避免

众所周知,前端兼容性问题一直存在,归根结底是各大浏览器的实现导致,我简单的将其总结为3类:

  • 功能或标准压根没有实现。
  • 实现的功能有BUG。
  • 实现的功能不符合标准。

我仔细想了一下,其实任何项目都会面临上面的问题:

  • 随着版本升级,越来越的功能和标准被引入进来,老版本停止维护不再升级。
  • BUG,试问哪个程序员敢说自己的代码没有BUG,况且浏览器是一个复杂庞大的项目。
  • 人非圣贤,想法和实践存在差距是必然的,对标准规范的个人理解偏差或者个人演绎,都可能导致实现和需求不一致。

典型问题

扯得有点远,最近了解到几个典型的移动端兼容性问题,它们分别是:

  • overflow:scroll滚动条,据说在android<3.0/ios <5.0平台,局部滚动是没有实现的(只有浏览器外部滚动条可以用),还有个别浏览器实现有BUG。(扩展链接
  • 高分辨率屏(例如:苹果retina屏),CSS 1px的border显得比较粗。(扩展链接
  • click延迟300ms的问题,点击穿透问题。 (扩展链接

我不是专业的前端开发,初次了解到这些问题让我感受到Html在移动端的标准化之路还有一定的路要走。

但是总不能甩手坐等标准化落实的那一天吧?所以我老老实实的看了一下几个WAP站的实现思路:糯米(m.nuomi.com),美团(m.meituan.com),斗鱼(m.douyu.com),熊猫(m.panda.tv),网易(m.163.com),新浪(m.sina.com.cn)… 你猜我发现了什么?

它们几乎都在WAP页底部放了一个提示条:请下载APP!

当然这个现象不能全怪WAP的兼容性坑爹,毕竟APP体验更好粘性更高,这些是目前WAP无法比拟的。

虽然各大网站都在WAP中将用户引导到APP,但是我后面还是会讲一下它们是如何在兼容性问题上取舍的。

H5

很多人现在把手机端网页叫做H5,我觉得可以进行如下区分:

  • WAP是为了覆盖最多的机型,无论是古董机还是高端机,都提供最最基础的浏览功能,WAP2.0标准使用的是最基础的HTML语法。
  • H5(HTML5)是借助新的HTML标准,提供动画、地理位置、音视频等更强大的功能,提供更好的体验,运行在比较新的机型上。

实际上大家已经很少考虑低端机型,比如:诺基亚N95,目前市面上除了安卓就是苹果,它们都能支持HTML5,只是支持的程度不同。

因此,现在工作中的WAP叫法,实际上就是指通过浏览器直接访问m.nuomi.com这种手机网页,其实现技术上或多或少用了H5的功能,但同时也尽量兼顾中低端机型的用户体验和兼容问题。

而H5现在主要指Hybird APP中的HTML5页面,什么是Hybird APP呢?例如:你在微信APP里看的公众号文章,在糯米/美团/淘宝的APP里使用的各种功能都是Hybird APP。它们的APP外壳都是android/ios代码实现的,内部嵌套订制的浏览器引擎(例如修改过的webkit),内容是HTML5写的页面,这是当今主要的H5存在形式。

为什么出现了Hybird APP呢(扩展链接)?一方面android/ios原生代码可以给html5代码提供统一的操作系统无关的解释执行环境,这样移动端的兼容问题可以大幅的解决,另外一方面html5可以从服务端动态更新,解决了原生的代码编译发布的周期问题。

一般中/大型互联网公司都会采用Hybird APP来提升研发效率,其实大家都是在艰难的向未来标准化的HTML5缓慢前行。

兼容性取舍

实际上,大家目前都不太愿意为移动浏览器的各种坑买单,思路归纳起来就是:有问题的特性尽量不用,迫不得已就抛弃低端机。

下面是我调研各WAP站后的一点看法,供大家参考决策。

滚动条

尽量使用浏览器默认的滚动条,即文档全局滚动。

如果想实现头部菜单/轮播区域的置顶固定,同时下面的主要内容区域局部滚动的这种效果,可以把头部fixed在浏览器顶部,并让主要内容区域margin-top对接到置顶区域,这样使用浏览器的默认滚动条感觉起来就和局部滚动效果一致了。

如果是某个浮层的DIV想局部滚动,那么优先使用overflow:scroll,也就是放弃掉不支持overflow:scroll的android/ios低端机和个别bug浏览器的用户。

如果你使用了局部overflow:scroll,那么就不要在意不同浏览器对滚动条样式的差异。

如果你实在不想放弃这些不支持overflow:scroll的手机,考虑用开源的iscroll5插件来取代overflow:scroll实现模拟的滚动条,但是它在这些低版本浏览器上性能表现可能差强人意,在某些高版本浏览器上可能无法正确工作。

(IOS某些版本的overflow:scroll无惯性滑动或者卡顿,需要添加特殊CSS处理,可以自行谷歌)

高分辨率屏

首先要搞清楚这档子事的原理,我简单的讲一下我的理解,如果看不懂可以自己扩展学习。

这个事情,我按3层分开理解(个人猜想,仅供参考):

硬件层

假设有个手机它宽假设5厘米,每一行有320个发光点,这叫320px的物理像素。但是,苹果手机研发的屏幕同样是5厘米宽,一行有640个发光点,这叫640px的物理像素。

操作系统层

苹果手机随着技术升级,同样5厘米放置的物理像素越来越多,640px….1080px层出不穷,原先的app按320px个物理像素画一条横线在320px物理像素的手机上是是可以填满屏幕的,但是这个app放在640px物理像素手机上画320px物理像素的横线就填不满屏幕了,这也太头疼了吧?

所以,操作系统对硬件层做了一次抽象,为了方便我们编程而屏蔽掉硬件变化带来的困扰:无论物理像素是640px的还是1080px,操作系统都告诉APP这个屏幕最大是320px,而这个320px就叫做设备无关(独立)像素

那么,当APP指定横线的长度是320px独立像素的时候,无论是640px还是1080px物理像素的苹果手机,都能填满一行,换句话说:对于640px物理像素的手机,1px独立像素=2px物理像素;对于1080px物理像素的手机,1px独立像素=3px物理像素,这个比例就叫做dpr(设备像素比)。

但是别忘了,苹果对屏幕的技术升级只是提升物理像素密度,屏幕的实际宽度一直是5厘米,提供的独立像素宽度一直是320px,可以得出一个结论:

APP画高度为1px独立像素的横线,在640/1080屏幕上看起来应该都是一样的粗细,只是在640px屏幕上对应的物理像素点少点,在1080px屏幕上对应的物理像素点更多。

看完下面的图就更清晰了:

iphone5采用retina高分辨率屏,假设暂且忽略两款手机的屏幕尺寸:上图的灰色区域高度是1px独立像素,在iphone5上对应2个物理像素而在老款iphone上对应1个物理像素,iphone5的2个物理像素加起来和旧款1个物理像素一样高,然而在实践中iphone5上这个线看起来要粗一些,这是为什么呢?

我个人猜测是因为人眼视觉造成的,极有可能是2个物理像素光源造成的错觉让我们认为线要粗一些(有知道真相的同学欢迎留言指点)。

CSS层

在css里的1px,叫做逻辑像素。它受到viewport的控制,当initial-scale=1时,逻辑像素:独立像素=1:1,当initial-scale=1=0.5时,逻辑像素:独立像素=2:1,就这么简单的原理。

一般我们H5页面都是viewport设置initial-scale=1,因此当屏幕是non-retina的时候1px逻辑像素=1px独立像素=1px物理像素,显示正常;当面临retina屏时,1px逻辑像素=1px独立像素=2px物理像素,就出现了著名的1px retina border问题。

因此网上流传着淘宝的一种解决方案:对于retina屏设置initial-scale=0.5,这样1px逻辑像素=0.5px独立像素=1px物理像素。


到底怎么办呢?我再次提出我的建议:

总是设置viewport的initial-scale=1。

尽量用CSS 1px像素做边框,虽然在retina下会粗一些,但是如果用一些比较浅的颜色(例如#eee),实际上肉眼是看不出多少怪异感的。(斗鱼,熊猫…都是这样)

如果你必须处理retina 1px的问题,那么必须使用css media query针对不同drp像素比套用不同的CSS来处理:

  • 用于分割线,可以采用background的渐变取代border,原理是1px的50%有颜色50%透明。(美团这样做)
  • 用于边框,并且需要圆角,那么建议用absolue+transform:scale的方案实现。

对于dpr不准确的浏览器只能认栽,代价无非是线宽一点。

300ms点击延迟和点击穿透

对于绝大多数浏览器和应用,300ms点击延迟问题通过设置viewport限制缩放后就可以解决,伴随着点击穿透问题也就无从出现了。

如果你想保持页面缩放能力,那么建议如下:

容忍300ms,继续使用click事件。

不能容忍300ms,使用fastclick透明的解决这个问题,继续使用click事件。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~