移动端的适配
一.适配的原因
屏幕分辨率引起的1px的border和图片模糊问题;如何去自适应不同宽度屏幕的手机等
二.手机参数
通过常见手机设备的参数了解常见的概念 :
Device | OPERATING SYSTEM | PHYS SIZE(英尺) | PHYSICAL SIZE(cm) | WIDTH(px) | H(px) | DEVICE WIDTH(px) | PX PER INCH | POPULARITY |
---|---|---|---|---|---|---|---|---|
Apple iPhone 5 | iOS | 4.0 | 10.0 | 640 | 1136 | 320 | 326 | 16 |
上面的意思:手机iphone 5--ios系统--4英寸--10cm--分辨率(物理像素)640ox*1136px--设备宽度(css像素)320px--像素密度PPI为320--流行程度16
2.1PHYS SIZE(英尺)和PHYSICAL SIZE(cm)
? 屏幕的尺寸对应屏幕对角线的长度
1in = 2.54cm,4in=4*2.54cm=10.16cm~10cm
2.2WIDTH和H
? 物理像素(physical pixel)是显示器的最小单位,也称设备像素(device pixel),可以看成是屏幕上的小发光点,它们可以呈现出我们看到的画面。
? 手机显示分辨率640*1136px表示手机的横向(WIDTH)有640个像素,纵向(H)1136个像素。
2.3DEVICE WIDTH(px)
设备宽度320像素,这里的像素是设备独立像素,即CSS像素;
设备独立像素(DIP,device-independent pixel,density-independent pixel),简单地来说设备独立像素就是:独立于设备的用于逻辑上衡量像素的单位。Web开发中就是指的CSS的逻辑像素。
2.4PX PER INCH
PX PER INCH(PPI),或者DPI(Dots Per Inch),都表示屏幕每英寸的像素数量,即像素的密度
一般的计算方法或者公式: DPI= 对角线分辨率 / 屏幕尺寸(PHYS SIZE)
对角线分辨率=
(iphone5的上,x表示横向的物理像素,y表示纵向的物理像素,Z就是2.1标题说的屏幕尺寸)
2.5设备像素比(devicePixelRatio)
DPR
设备像素比DPR(devicePixelRatio)是默认缩放为100%的情况下,设备像素(也称物理像素)和CSS像素的比值(设备独立像素)。
设备像素比=设备像素(物理像素)/设备独立像素(CSS像素)
iphone5 的DPR=640px/320px=2
表示水平上css的1px为2个物理像素(多少DPR代表水平css的1px等于多少个物理像素)
所以css的1px等于4个物理像素(水平+垂直)
正常屏幕上css的1px对应屏幕一个红色小方块(1px物理像素),在iphone5的手机上css的1px对应4个红色小方块
Retina视网膜屏幕
通过DPR为2可以了解到Phone5 使用的是Retina视网膜屏幕,在iphone5的手机上css的1px对应4个红色小方块(4个物理像素)
css的1px等于多少个物理像素
css的1px等于多少个物理像素受两个因素影响:
1.默认缩放为100%情况下,可以通过DPR确定css的1px为多少个物理像素
2.用户的缩放也会影响。当用户把页面放大一倍,那么CSS中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,CSS中1px所代表的物理像素也会减少一倍。
https://www.zhihu.com/question/21149600(像素与分辨率)
https://www.cnblogs.com/wangzhenling/p/8989810.html
2.6 1px的问题和图片的模糊
2.6.11px的border问题
由于Retina视网膜屏幕的原因,所以css的1px宽的border可能等于2px/3px物理像素,而设计师想要的是1个物理像素宽的大小。所以css设置0.5px,就可以解决,但不是手机都支持0.5px,所以需要另外的解决,比如transform缩放,或者flexible方案(该方案正被淘汰)等
2.6.2图片的模糊
一个位图像素对应1个物理像素,可以使得图片得到清晰呈现,但在dpr为2(比如iphone5),1个位图像素对应了四个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,导致图片看起来比较模糊.
(w:宽;h:高)如果640px的设计稿上有一个图标是60w,60h,表示它的图像分辨率是60*60=360px;那么就要用30w,30h的img表示。因为一个css像素等于4个物理像素,30w,30h的img里面就有30乘30乘4=360个物理像素,所以能够达到1个位图像素:1个物理像素
? 所以就是为啥320px宽的手机使用640px的设计稿
? 最好的解决方法:不同的dpr下,加载不同的尺寸的图片。不管是通过CSS媒体查询,还是通过JS条件判断都是可以的。
三.视口
默认情况下,手机浏览器会将网页渲染在比手机屏幕宽的虚拟窗口上”viewport“上,所以用户需要平移和缩放网页来看网页,这样对于用户体验极差。
移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),这里viewport是layout viewport布局视口,视口分三种
3.1visual viewport
顾名思义,视觉上的视口,就是手持设备物理屏幕的可视区域,等于屏幕宽度
window.innerWidth/Height
3.2layout viewport
手机上为了容纳为桌面浏览器设计的网站,默认布局视口宽度远大于屏幕宽度,为了让用户看到网站全貌,它会缩小网站。这个视口就是HTML页面布局的区域,并且可以通过viewport meta标签控制;
document.documentElement.clientWidth获取layout viewport的宽度
meta 标签控制layout viewport的语法
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。0-1
maximum-scale:允许用户缩放到的最大比例。0-1
minimum-scale:允许用户缩放到的最小比例。0-1
user-scalable:用户是否可以手动缩放。yes/no
3.3idea viewport
页面布局的宽度能够等于视口的宽度时,就是idea viewport,在此情况下,用户不用进行平移和缩放来查看页面,因为页面是100%呈现在手机屏幕的区域内,在不同尺寸下都能基本表现一致。有什么办法实现layout=visual呢,使用
<meta name="viewport" content="width=device-width">
四.适配方案
为了解决手机不同尺寸的问题,需要有一些适配方案,比如一个按钮在不同尺寸的手机下能够完整呈现,随着大尺寸手机放大,小尺寸手机缩小。rem方案就可以解决
4.1百分比布局
- 设置固定屏幕为理想视口宽度
- 少许的媒体查询设置字体,或者配合rem(如果需要,这样字体可以有所变化,或者font-size:16rem)
- 水平百分比布局(如60%)
- 水平方向部分也可以使用弹性布局(flex)
- 高度是固定(也就是height="50px",使用px单位)
例子:实现一个手机屏幕的顶部
header:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
body:
<header>标题<header>
<style>
.header{
width:100%;
heigth:50px;
font-size:16rem;
background:red;
}
<style>
使用场景: 实现简单的布局、可以在移动设备中水平表现良好差异不大。
4.2rem布局
rem是css3的字体单位,特点是跟html的font-size扯上关系,html的font-size为16px;设置某个元素的宽度为2rem,即32px。
4.2.1简单的尺寸适配 媒体查询
@media screen and (min-width: 320px) {
html {font-size: 50px;}
}
@media screen and (min-width: 360px) {
html {font-size: 56.25px;}
}
4.2.2复杂的尺寸适配 js
假设,640px的设备 1rem = 100px
公式: rem = document.clientWidth / 640 * 100px;
注意:chrome浏览器字体小于12px(会被重置为12px)
(如果不想1rem=100px,也可自行设定,比如640设计稿一个图标宽度40px,直接css定义宽度为40/100rem,在640的手机屏上根据公式是40px,320手机屏幕上是20px.使用rem就直接除就好了,然后这里有涉及到320的手机为啥使用640设计稿的问题)
!(function(doc, win) {
var docEle = doc.documentElement,
evt = "onorientationchange" in window ? "orientationchange" : "resize",
fn = function() {
var width = docEle.clientWidth;//屏幕的宽度
width = width < 320 ? 320 : width;
width = width > 640 ? 640 : width;
width && (docEle.style.fontSize = 100 * (width / 640) + "px");//640是设计稿的宽度
};
win.addEventListener(evt, fn, false);
doc.addEventListener("DOMContentLoaded", fn, false);
}(document, window));
场景:rem方案可以实现随着设备尺寸的变宽,元素高度和宽度都相应放大,一般百分比和rem都是组合使用的,需要宽度自适应屏幕就百分比,或者弹性盒子,想元素的宽度和高度能随手机尺寸变化就rem.
4.3推荐方案
淘宝的flexible方案
hotcss
都是通过设置html的font-size和initial-scale来达到适配,html的font-size是为了不同终端尺寸的适配,initial-scale是为了达到1css像素等于1个物理像素(推荐1的js和rem方案可以参考)
vw方案(流行,查看推荐2)
将视口分为100份,准确的来说1vw=visual viewport/100,visual viewport=window.innerWidth;
假如设计稿640px,dpr=1(dpr为1为了说明例子,vw适配与dpr无联系)的情况下,如果设计稿完全适应屏幕,此时1vw=640/100px;一个图标60* 60,宽度60px等于60/6.4=9.375vw;屏幕变成320px时候,1vw=320/100=3.2px,该图标(已经设置为9.375vw)变成9.375 *3.2=30px。原来在640px,宽是60,320px的时候宽是30,尺寸屏幕之比会等于图片缩放之比,可以实现宽度随尺寸等比缩放。
https://www.w3cplus.com/mobile/vw-layout-in-vue.html(推荐2)
https://www.cnblogs.com/superlizhao/p/8729190.html(推荐1)