手机web端发展现状——“杂屏”时代:
手机web端较web前端页面相对简单,使用的技术都是html+css+js。pc端浏览器种类繁多,不仅要兼容IE低版本浏览器最麻烦的是还需要适配不同浏览器效果;而手机端则避免了这些问题,Android原生浏览器、苹果的Safari、谷歌的Chrome都是基于Webkit开源内核开发的,但是五花八门的屏幕适配成为难点和重点。早期移动端开发,对于终端设备适配问题只属于Android系列,只不过很多设计师常常忽略Android适配问题,只出一套iOS平台设计稿。但随着iPhone6,iPhone6+的出现,从此终端适配问题不再是Android系列了,也从这个时候让移动端适配全面进入到“杂屏”时代。
为了应对这多么的终端设备,整个手淘设计师和前端开发的适配协作基本思路是:
选择一种尺寸作为设计和开发基准定义一套适配规则,自动适配剩下的两种尺寸(其实不仅这两种,你懂的)特殊适配效果给出设计效果-
一、传统做法(响应式布局)的弊端
|
|
(1).item类在所有设备下的width都是3.4rem,但在不同分辨率下的实际像素是不一样的,所以在有些分辨率下,width的界面效果不一定合适,有可能太宽,有可能太窄,这时候就要对width进行调整,那么就需要针对.item写媒介查询的代码,为该分辨率重新设计一个rem值。然而,这里有7种媒介查询的情况,css又有很多跟尺寸相关的属性,哪个属性在哪个分辨率范围不合适都是不定的,最后会导致要写很多的媒介查询才能适配所有设备,而且在写的时候rem都得根据某个分辨率html的font-size去算,这个计算可不见得每次都那么容易,比如40px / 23.5px,这个rem值口算不出来的!由此可见这其中的麻烦有多少。
传统做法是对代码做响应式设计。但是从工作量和复杂度方面来考虑,它有以下几个不足:
(2)以上代码中给出的7个范围下的font-size不一定是合适的,这7个范围也不一定合适,实际有可能不需要这么多,所以找出这些个范围,以及每个范围最合适的font-size也很麻烦
(3)设计稿都是以分辨率来标明尺寸的,前端在根据设计稿里各个元素的像素尺寸转换为rem时,该以哪个font-size为准呢?这需要去写才能知道。
京东APP总结:与设计稿有误差,高清屏反而不清楚
二、基本概念简介
| 概念 |
含义 |
|---|---|
| 视窗 viewport |
|
| 物理像素 physical pixel |
物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。 |
| CSS像素 | CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。 |
| 设备独立像素 density-independent pixel |
|
| 设备像素比 device pixel ratio |
设备像素比 = 物理像素 / 设备独立像素。 简单理解:iPhone6的设备宽度和高度为375pt * 667pt,可以理解为设备的独立像素,而其dpr为2,根据上面公式,我们可以很轻松得知其物理像素为750pt * 1334pt。 |
| rem |
简单的理解:rem就是相对于根元素<html>的font-size来做计算。 |
| meta标签 |
|
- layout viewport 和 visual viewport
设备的pixels和CSS的pixels的区别
在css中我们一般使用px作为单位,在桌面浏览器中css的1个像素往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的一个错觉,那就是css中的像素就是设备的物理像素。
但实际情况却并非如此,css中的像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素是不同的。在为桌面浏览器设计的网页中,我们无需对这个津津计较,但在移动设备上,必须弄明白这点。
在早先的移动设备中,屏幕像素密度都比较低,如iphone3,它的分辨率为320x480,在iphone3上,一个css像素确实是等于一个屏幕物理像素的。后来随着技术的发展,移动设备的屏幕像素密度越来越高,
从iphone4开始,苹果公司便推出了所谓的Retina屏,分辨率提高了一倍,变成640x960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,像素却多了一倍,这时,一个css像素是等于两个物理像素的。
还有一个因素也会引起css中px的变化,那就是用户缩放。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。
下列图片将清楚的解释这个概念。如图1-1.有4个1像素,缩放为100%的html元素,CSS的pixels完整的和设备的pixels重叠
当我们缩小浏览器时,CSS的pixels开始收缩,导致1单位的设备的pixels上重叠了多个CSS的pixels,
同理,放大浏览器时,相反的事情发生了,CSS的pixels开始扩大,导致1单位的CSS的pixels上重叠了多个设备的pixels,
在缩放级别为100%时,1单位的CSS的pixel是严格相等于1单位的设备pixel
所谓的高清屏,就是在相同的css像素下展示了更多的物理像素点
-
在苹果的规范中,meta viewport 有6个属性如下:
width |
设置layout viewport 的宽度,为一个正整数,或字符串"width-device" |
initial-scale |
设置页面的初始缩放值,为一个数字,可以带小数 |
minimum-scale |
允许用户的最小缩放值,为一个数字,可以带小数 |
maximum-scale |
允许用户的最大缩放值,为一个数字,可以带小数 |
height |
设置layout viewport 的高度,这个属性对我们并不重要,很少使用 |
user-scalable |
是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许 |
这些属性可以同时使用,也可以单独使用或混合使用,多个属性同时使用时用逗号隔开就行了。
三.手淘团队H5适配的开源库——lib-flexible
H5适配的开源库lib-flexible
淘宝淘宝的尺寸也是使用了rem,随着分辨率的变化,页面元素的尺寸和间距都相应变化。
这样整个网页在设备内显示时的页面宽度就会等于设备逻辑像素大小,也就是device-width。
-
-
这个device-width的计算公式为:设备的物理分辨率/(devicePixelRatio * scale),在scale为1的情况下,device-width = 设备的物理分辨率/devicePixelRatio 。
-
devicePixelRatio称为设备像素比,每款设备的devicePixelRatio都是已知,并且不变的,目前高清屏,普遍都是2,不过还有更高的,比如2.5, 3 等。
淘宝触屏版布局的前提就是viewport的scale根据devicePixelRatio动态设置:在devicePixelRatio为2的时候,scale为0.5;在devicePixelRatio为3的时候,scale为0.3333。
这么做目的是为了保证页面的大小与设计稿保持一致,比如设计稿如果是750的横向分辨率,那么实际页面的device-width,以iphone6来说,也等于750。
-
- 把视觉稿中的
px转换成rem:html元素的font-size的计算公式,font-size = deviceWidth / 10。淘宝他们用的设计稿是750,所以html的font-size就是75,如果某个元素时150px的宽,换算成rem就是150 / 75 = 2rem。
- 把视觉稿中的
总结下淘宝的这些做法:(flexible实际上就是能过JS来动态改写meta标签,代码见项目)
-
-
(1)动态设置viewport的scalevar scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); -
(2)动态计算html的font-sizedocument.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; -
(3)布局的时候,各元素的css尺寸=设计稿标注尺寸/设计稿横向分辨率/10
-
最后还有两个注意事项:
- 文本字号不建议使用
rem
我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到不是更大的字体而是更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,所以我们不希望出现13px和15px这样的尺寸。
如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。
-
淘宝设置了一个临界点
当设备竖着时横向物理分辨率大于1080时,html的font-size就不会变化了,分辨率已经可以去访问电脑版页面了。
简单理解: 将font-size设置为设计图宽度的十分之一,宽度永远等于10rem,无论设备屏幕怎么变化,比例永远不会改变,实现多屏适配
四、围观网易适配方案
假设它的设计稿竖直放时的横向分辨率为640px,为了计算方便,取一个100px的font-size为参照,那么body元素的宽度就可以设置为width: 6.4rem,。这个deviceWidth就是viewport设置中的那个deviceWidth。
deviceWidth/font-size=640/100,于是html的font-size=deviceWidth / 6.4
展开源码
总结下网易的这种做法:
-
(1)先拿设计稿竖着的横向分辨率除以100得到body元素的宽度:
如果设计稿基于iphone6,横向分辨率为750,body的width为750 / 100 = 7.5rem
如果设计稿基于iphone4/5,横向分辨率为640,body的width为640 / 100 = 6.4rem
-
(2)布局时,设计图标注的尺寸除以100得到css中的尺寸:
播放器高度为210px,写样式的时候css应该这么写:height: 2.1rem。之所以取一个100作为参照,就是为了这里计算rem的方便!
-
(3)在dom ready以后,通过以下代码设置html的font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px',6.4只是举个例子,如果是750的设计稿,应该除以7.5。
-
(4)font-size需要额外的媒介查询,并且font-size不能使用rem,如网易的设置:
@media screen and (max-width:321px){ .m-navlist{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .m-navlist{font-size:16px} } @media screen and (min-width:400px){ .m-navlist{font-size:18px} }
最后还有两个注意事项:
第一,如果采用网易这种做法,视口要如下设置:
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
第二,当deviceWidth大于设计稿的横向分辨率时,html的font-size始终等于横向分辨率/body元素宽:
是因为当deviceWidth大于640时,则物理分辨率大于1280(这就看设备的devicePixelRatio这个值了),应该去访问pc网站了。