如何快速的做到手机端的页面兼容
为什么要写这篇文章
- 前段时间做了一个项目,客户要求最低兼容Iphone5S
- 在线上运营的项目,客户总是提出兼容很差的问题,之前一直拖着,不曾解决,现在统计处理一下
学习重点
正文
前端兼容的痛点
在实际项目开发过程中,作为前段经验并不丰富的后端开发人员,总是会在UI上栽跟头。手机中实际展示效果总是跟模拟器中的展示效果差之千里。
举个例子,左边,为我在chrome浏览器中调试的页面,右侧为IPhone5s打开之后的页面效果。
这样的页面,别说客户无法忍受,如果这个页面不是我写的,我必然会找到那个始作俑者,把这个页面的截图狠狠的甩到她脸上,问她,你是怎么做的?这样的页面让客户怎么看,这样的按钮,让用户怎么点,难道想点个累计扫码,一不小心手指稍稍偏了一点儿,页面就关闭了?
作为一个还算合格的后端开发人员。
我保证,我确信,我真的已经努力做了兼容,所有高度都是动态分配,包括页面高度,都由Js根据屏幕可见高度努力算出来,可为什么呈现给用户的效果还会是这样?这样的惨不忍睹。
代码可以分享给大家:
//获取屏幕的高度
var screenHeight = window.screen.availHeight;
//奖项Div距离顶部的高度,为页面总高度的4.5分之一
$(self._contentPrize).css("margin-top", screenHeight / 4.5);
//初始化红包弹出框
//红包Div距离顶部的高度为自己高度的20%
$("#redPackageContent").css("padding-top", $("#redPackageContent").height() * 0.20);
//红包金额的Div显示距离顶部为红包页面高度的15%
$("#redPackageInfo").css("padding-top", $("#redPackageContent").height() * 0.15);
//红包页面底部的按钮Padding红包页面的高度为红包页面高度的20%
$("#redPackagebutton").css("padding-top", $("#redPackageContent").height() * 0.20);
这段代码是试出来的最佳高度,可能没有任何逻辑可言。在一塌糊涂的UI面前,程序员的逻辑已被击溃。
刚开始我以为是微信浏览器自带底部导航栏的问题,但,将导航栏的底部高度减去之后,依然无法做到兼容。就算做到兼容主流手机,依然无法保证做到全兼容。
主流手机的分辨率
苹果手机:
手机型号 | 手机尺寸 | 分辨率 |
---|---|---|
iPhone 4S | 3.5寸 | 960 × 640 |
iPhone 5(5S/5C) | 4.0寸 | 1136 x 640 |
iPhone 6 | 4.7寸 | 1334 x 750 |
iPhone 6 Plus | 5.5寸 | 2208 x 1242 (1920x1080) |
iPhone 6S | 4.7寸 | 1334 x 750 |
iPhone 6S Plus | 5.5寸 | 2208 x 1242 (1920x1080) |
iPhone SE | 4寸 | 1136 x 640 |
iPhone 7 | 4.7寸 | 1334 x 750 |
iPhone 7 Plus | 5.5寸 | 2208 x 1242 (1920x1080) |
iPhone 8 | 4.7寸 | 1334 x 750 |
iPhone 8 Plus | 5.5寸 | 2208 x 1242 (1920x1080) |
iPhone X | 5.8寸 | 2436 × 1125 |
华为手机:
华为P30Pro | 6.47寸 | 2340×1080 |
华为 Mate 20 | 6.53寸 | 2244×1080 |
华为畅享9 PLUS | 6.5寸 | 2340×1080 |
华为 Mate 20 Pro | 6.39寸 | 3120x1440 |
华为P30 | 6.1寸 | 2340×1080 |
华为Nova 4 | 6.4寸 | 2310 x 1080 |
华为Nova 4e | 6.15寸 | 2312×1080 |
华为Nova 5 | 6.39寸 | 2340x1080 |
华为 Mate 20 X | 7.2寸 | 2244x1080 |
华为麦芒 8 | 6.21寸 | 2340x1080 |
华为 Mate 20 RS | 6.39寸 | 3120x1440 |
华为畅享9S | 6.21寸 | 2340x1080 |
华为畅享9 | 6.26寸 | 1520x720 |
华为 P20 Pro | 6.1寸 | 2240x1080 |
华为 nova 5i | 6.4寸 | 2310×1080 |
华为畅享 9e | 6.09寸 | 1560x720 |
华为 P20 | 5.8寸 | 2244×1080 |
华为 畅享 MAX | 7.12寸 | 2244×1080 |
华为 nova 3i | 6.3寸 | 2340×1080 |
华为 nova 3 | 6.3寸 | 2340 x 1080 |
华为 mate 10 pro | 6.0寸 | 2160x 1080 |
华为 nova 2s | 6.0寸 | 2160x1080 |
华为 畅享8e | 5.7寸 | 1440*720 |
华为 麦芒7 | 6.3寸 | 2340 x 1080 |
华为 nova 2 Plus | 5.5寸 | 1920x 1080 |
华为 畅享8 Plus | 5.93寸 | 2160x 1080 |
华为 nova 青春版 | 5.2寸 | 1920x 1080 |
华为 nova 3e | 5.84寸 | 2280x1080 |
华为 Mate 9 | 5.9寸 | 1920x1080 |
华为 畅享7 Plus | 5.5寸 | 1280x720 |
华为 P10 | 5.1寸 | 1920x1080 |
华为 麦芒6 | 5.9寸 | 2160x1080 |
华为 P10 Plus | 5.5寸 | 2560 x 1440 |
华为 畅享 8e 青春 | 5.45寸 | 1440x72 |
为彻底解决兼容的问题,在众多兼容插件中找到了最适合自己的lib-flexible插件,该插件主要使用rem进行布局。
- 前期准备工作
- 插件原理
前期准备工作
在使用该插件前,我们只需要做两件事情,
第一,下载 lib-flexible.js文件并引用至我们的项目当中。
第二,设置viewport,设置代码如下:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
这样设置的目的在于网页在设备内的页面宽度就会等于逻辑设备像素大小。
第三,在body中添加如下设置:
<body ontouchstart></body>
插件原理
lib-flexible插件是基于设备的宽度的像素为基础像素,也就是device-width。在插件中,统一认为设备的宽度为10rem。再根据该设备的宽度像素,计算出1rem所占像素。
device-width的计算公式为:
设备的物理分辨率/(devicePixelRatio * scale),在scale为1的情况下,device-width = 设备的物理分辨率/devicePixelRatio
devicePixelRatio称为设备像素比,每款设备的devicePixelRatio都是已知,并且不变的,目前高清屏,普遍都是2,不过还有更高的,比如2.5, 3 等,魅族note的手机的devicePixelRatio就是3。淘宝触屏版布局的前提就是viewport的scale根据devicePixelRatio动态设置。
这么做目的当然是为了保证页面的大小与设计稿保持一致了,比如设计稿如果是750的横向分辨率,那么实际页面的device-width,以iphone6来说,也等于750,这样的话设计稿上标注的尺寸只要除以某一个值就能够转换为rem了。通过js设置viewport的方法如下。
var scale = 1 / devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
lib-flexible布局的第二个要点,就是html元素的font-size的计算公式,font-size = deviceWidth / 10:
接下来要解决的问题是,元素的尺寸该如何计算,比如说设计稿上某一个元素的宽为150px,换算成rem应该怎么算呢?这个值等于设计稿标注尺寸/该设计稿对应的html的font-size。拿淘宝来说的,他们用的设计稿是750的,所以html的font-size就是75,如果某个元素时150px的宽,换算成rem就是150 / 75 = 2rem。总结下淘宝的这些做法:
- 动态设置viewport的scale
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
- 动态计算html的font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
- 布局的时候,各元素的css尺寸=设计稿标注尺寸/设计稿横向分辨率/10
- font-size可能需要额外的媒介查询,并且font-size不使用rem。
最后。lib-flexible设置了一个临界点,当设备竖着时横向物理分辨率大于1080时,html的font-size就不会再变化。