移动端屏幕千差万别,H5页面要如何实现多终端的适配呢?这里对从网上收集的一些资料做简单的记录。
输入
这里的输入是指设计师给出的设计稿,设计师在输出设计稿的时候不可能遍历所有的终端,他们会按照一定的规则与前端工程师达成一致:
选择一种尺寸作为设计和开发基准
定义一套适配规则,自动适配剩下的屏幕
特殊适配效果给出设计效果
如上图所示,设计师常选择iPhone6作为基准设计尺寸,交付给前端的设计尺寸是按750px * 1334px为准(高度会随着内容多少而改变)。前端开发人员通过一套适配规则自动适配到其他的尺寸。
这里重点要说的就是前端工程师采用什么样的适配规则去完成其他平台的适配工作。
在具体讨论适配规则之前先来了解一些基本概念:
基本概念
物理像素(physical pixel)
物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。所谓的一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素,也就是说,多倍屏以更多更精细的物理像素点来显示一个CSS像素点,在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。
CSS像素
CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。CSS像素顾名思义就是我们写CSS时所用的像素。
注:在不同屏幕上css像素所呈现的物理尺寸是一致的
设备像素比dpr(device pixel ratio)
设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:
设备像素比 = 物理像素 / 设备独立像素
三个viewport的理论
移动设备上有三个viewport。包括layout viewport、visual viewprt、ideal viewport
layout viewport
首先,移动设备上的浏览器认为自己必须能让所有的网站都正常显示,即使是那些不是为移动设备设计的网站。但如果以浏览器的可视区域作为viewport的话,因为移动设备的屏幕都不是很宽,所以那些为桌面浏览器设计的网站放到移动设备上显示时,必然会因为移动设备的viewport太窄,而挤作一团,甚至布局什么的都会乱掉。也许有人会问,现在不是有很多手机分辨率都非常大吗,比如768x1024,或者1080x1920这样,那这样的手机用来显示为桌面浏览器设计的网站是没问题的吧?前面我们已经说了,css中的1px并不是代表屏幕上的1px,你分辨率越大,css中1px代表的物理像素就会越多,devicePixelRatio的值也越大,这很好理解,因为你分辨率增大了,但屏幕尺寸并没有变大多少,必须让css中的1px代表更多的物理像素,才能让1px的东西在屏幕上的大小与那些低分辨率的设备差不多,不然就会因为太小而看不清。所以在1080x1920这样的设备上,在默认情况下,也许你只要把一个div的宽度设为300多px(视devicePixelRatio的值而定),就是满屏的宽度了。回到正题上来,如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做 layout viewport。这个layout viewport的宽度可以通过document.documentElement.clientWidth 来获取。
注:屏幕的layout viewport要比屏幕的可视区域大,主要是为了使pc时代的页面在手机端能正常展示,只不过会存在横向滚动条。
visual viewport
有了layout viewport,我们还需要一个视口用来承载它,这个视口可以简单的认为是手持设备物理屏幕的可视区域,我们称之为(视觉视口)visual viewport。这是一个比较直观的概念,因为你能看得见你的手机屏幕。
对于visual viewport,开发者一般只需要知道它的存在和概念就行,因为无法对它进行任何设置或者修改。很明显,visual viewport的尺寸不会是一个固定的值,甚至每款设备都可能不同。大致列几种常见设备的visual viewport尺寸:
iPhone4~iPhone5S: 320*480px
iPhone6~iPhone6S: 375*627px
iPhone6 Plus~iPhone6S Plus: 414*736px
ideal viewport
现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做 ideal viewport,也就是第三个viewport——移动设备的理想viewport。
ideal viewport是我们移动开发中最为关注的一个视口,我们平时设置的meta属性也都与该视口有关
这里不太懂ideal与visual的区别
利用meta标签对viewport进行控制
在移动端页面开发时我们会直接在页面中添加如下语句,那么该语句的作用是什么呢?
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,user-scalable=no">
首先ideal viewport是默认不存在的,我们的页面运行在移动端浏览器时其实是在layout viewport中布局和展示(默认的layout viewport视口的尺寸是很大的),为了使页面能够在ideal viewport大小的视口中布局展示,我们只需要设置
<meta name="viewport" content="width=device-width">
即将layout viewport的宽度设置成设备宽度
以下代码达到的效果同上
<meta name="viewport" content="initial-scale=1">
即将页面的初始缩放值设置为1也可以将layout viewport的宽度设置成设备宽度。Why?Why?
要解释这里的原因需要搞清楚这里的缩放是谁相对于谁的缩放。
这里是对页面的布局区域进行缩放,即对layout viewport进行缩放。
缩放是相对于 ideal viewport来进行缩放的,当对ideal viewport进行100%的缩放,也就是缩放值为1的时候,不就得到了 ideal viewport嘛。所以两段代码实现的效果一致。
最后,总结一下,要把当前的viewport宽度设为ideal viewport的宽度,既可以设置 width=device-width,也可以设置 initial-scale=1,但这两者各有一个小缺陷,就是iphone、ipad以及IE 会横竖屏不分,通通以竖屏的ideal viewport宽度为准。所以,最完美的写法应该是,两者都写上去,这样就 initial-scale=1 解决了 iphone、ipad的毛病,width=device-width则解决了IE的毛病:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
适配规则
flexable.js
flexable.js是手机淘宝解决不同设备的适配问题,其核心有三方面:
- 动态改写<meta>标签
- 给<html>元素添加data-dpr属性,并且动态改写data-dpr的值
- 给<html>元素添加font-size属性,并且动态改写font-size的值
具体可参照文章介绍,这里不再赘述。
简单规则
首先在index.html中添加
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,user-scalable=no">
动态设置html元素的font-size
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth
if (!clientWidth) return
docEl.style.fontSize = parseInt(clientWidth / 375 * 100) + 'px'
var targetRem = parseInt(clientWidth / 375 * 100)
if (targetRem % 2) { targetRem++ }
docEl.style.fontSize = targetRem + 'px'
}
if (!doc.addEventListener) return
win.addEventListener(resizeEvt, recalc, false)
doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window);
由于设计师给出的设计稿是按照iphone6给出的,此时设备宽度正好为375px,在该设备上font-size为100px,即此时1rem = 100px,之后就可以根据设计师给出的标注按照该标准由px转化为rem就可以了。
总结
可以看到,上面提到的两种适配规则大同小异,都是设置meta标签,然后动态的设置html标签的font-size,在页面开发时将标注图标注的尺寸按照标准的font-size值将px转化为rem就可以了。