说到移动端适配,首先我们需要先搞清楚一些基础知识,所以本文路线是先了解像素,dpr,视口等基础知识,然后再整理出移动端适配方案。
像素其实分为两种,分别是物理像素和CSS像素
视口也叫作初始包含块,之所以叫这个名字,是因为它包含了元素,它的宽度是所有CSS百分比宽度推算的根源。
在桌面浏览器,视口的宽度等同于浏览器窗口的宽度,高度即为浏览器窗口的高度。但移动端就有点复杂了,移动端的视口分为布局视口和视觉视口。
布局视口(layout viewport)
说布局视口之前,我们先说一下桌面端的页面放到移动端浏览器后出现的问题:由于早期的页面很多采用固定宽度的布局,导致放在移动端的小窗口下出现横向的滚动条,不便于用户查看,所以浏览器厂商研究出了布局视口。布局视口的宽度一般在768px~1024px(由浏览器厂商设置),常见宽度980px,虽然设置了很大的宽度,但在没有手动设置宽度的情况下,布局视口仍会容纳在一屏里(说白了,就是把980px的东西装在320px的屏幕里),这样,浏览器会避免出现横向滚动条。
设置布局视口宽度:<meta name="viewport" content="width=640">
获取布局视口宽度:document.documentElement.clientWidth
布局视口除了和meta设置的width有关,还和scale有关,scale后面会说。视觉视口(visual viewport)
用户正在看到的网页的区域,大小是屏幕中CSS像素的数量。
获取视口宽度:window.innerWidth/Height
初始状态下,一般视觉视口会等于布局视口。理想视口
当布局视口的宽度达到理想状态时,就是理想视口,理想视口中的页面有最理想的宽度,用户进入页面不用缩放。
实现方法:<meta name="viewport" content="width=device-width">(即设置布局视口宽度为设备宽度)
原理:可以理解为修改dppx,举个例子,假设一屏幕DPR为2,即1px对应2pt,如果这个时候,我们设置scale=0.5,那么dppx就会从2变成1,即1px对应1pt。所以,通过缩放我们可以调整自己所能控制的最小物理像素粒度。
缩放会影响布局视口的大小,因为浏览器会尽量让布局视口铺满屏幕,所以当我们设置scale=0.5时,布局视口的宽度会自动变为原来的两倍。
具体如下图所示。
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<script>
console.log(document.documentElement.clientWidth); //结果为375
</script>
<meta name="viewport" content="width=device-width,initial-scale=0.5">
<script>
console.log(document.documentElement.clientWidth); //结果为750
</script>
可能有人会问,scale的初始值是多少?其实这取决于viewport的宽度,因为浏览器会尽量让布局视口铺满全屏,所以浏览器会根据布局视口的大小动态调整scale的初始值大小,从而使布局视口铺满全屏。
使用缩放的好处:对于DPR为2或更高的屏幕,如果不做缩放操作,我们所能控制的最小物理像素粒度是2pt或更多物理像素,这样带来了两个问题。
如果设计图上某个边框标识的大小是1px,那说明设计师想让这个边框在任何屏幕上都是1像素,在普通屏幕上,不会有问题,但在retina这种高清屏上,当我们用1px修饰border时,实际上会有2pt渲染为border,导致border看上去比普通屏的border宽。
<style>
#log {
border: 1px solid black;
}
</style>
<div id="log"></div>
解决这两个问题的方法就是缩放,我们把scale设置为1/dpr。
meta.setAttribute(‘content‘, ‘initial-scale=‘ + 1/dpr + ‘, maximum-scale=‘ + 1/dpr + ‘, minimum-scale=‘ + 1/dpr + ‘, user-scalable=no‘);
这样1px就对应1pt,我们就可以解决1px border问题和图片的高清问题了。
固定高度,宽度自适应
即垂直方向使用固定大小,水平方向使用百分比,flex。
<meta name="viewport" content="width=device-width,initial-scale=1">
适合场景:比较适合列表式的结构。固定宽度,viewport缩放
开发页面时完全按照和设计图1:1的比例开发,设计图,页面,视口宽度使用同一个宽度,单位使用px即可,由于浏览器会尽量将布局视口铺满全屏,所以浏览器会自动帮助我们缩放。举个例子,假设设计图是640px宽,那我们这样设置。
<meta name="viewport" content="width=640">
这个时候会发现,浏览器会帮助我们将页面铺满全屏,而且这是绝对的等比例缩放。图片、文字等等所有元素都被缩放在手机屏幕中。rem做宽度,viewport缩放
根据屏幕宽度设定rem值,需要适配的元素都使用rem为单位,不需要适配的元素还是使用 px 为单位。
总共分两步:
动态设置font-size
document.getElementsByTagName(‘html‘)[0].style.fontSize = window.innerWidth / 10 + ‘px‘;
缩放viewport
meta.setAttribute(‘content‘, ‘initial-scale=‘ + 1/dpr + ‘, maximum-scale=‘ + 1/dpr + ‘, minimum-scale=‘ + 1/dpr + ‘, user-scalable=no‘);
第二步是对页面适配的优化,修改scale是为了解决前面说到的1px border问题。
淘宝的Flexible使用的就是这种方案,而且它加了data-dpr属性,这样我们就可以根据不同的DPR设置不同的样式。
方案一比较适合列表这种比较固定的结构,方案二适合的场景比较多,而且实现简单,但需要注意它会将页面的所有元素都缩放,方案三适合的场景是页面内有些元素需要适配,有些元素不需要适配。总体来讲,方案二和方案三是比较常用的方式。
原文:http://www.cnblogs.com/chenshizhutou/p/6701198.html