参考
https://github.com/amfe/article/issues/17
https://github.com/amfe/lib-flexible
http://www.cocoachina.com/webapp/20150715/12585.html
弹性布局:flex、grid、居中、calc()
样式选择:媒体查询、媒体信息作为选择器前缀(例如)
相对尺寸:%,rem(设置)、vw
自适应总体方案:高度用px、字体大小用px、宽度用vw或rem
px(pixels):物理像素,硬件像素,设备像素,显示像素
dp,dip(deveice independent pixels):逻辑像素、设备无关像素、CSS像素
pt(point):1/72英寸
dpr(devicePixelRatio): 设备像素比,即 1dip包含了多少个px,即px数 / dip数
ppi,dpi:像素密度(像素每英寸),斜向一英寸里的物理像素数量
em: 相对于父元素的font-size的相对单位。
rem: 相对于根元素的font-size的相对单位。
vw: 1% 布局视口宽度
vh: 1% 布局视口高度
resolution:分辨率,横向物理像素数 * 纵向物理像素数
设备尺寸列表 https://material.io/devices/
ppi与默认dpr对应关系
^ | 显示分辨率 | ppi | 默认dpr |
---|---|---|---|
ldpi | 240*320 | 120 | 0.75 |
mdpi | 320*480 | 160 | 1.0 |
hdpi | 480*800 | 240 | 1.5 |
xhdpi | 720*1280 | 320 | 2.0 |
Retina屏(视网膜屏): ppi 大于320
案例 – iPhone5
resolution:640 * 1136,屏幕尺寸:4英寸
ppi = 开根号(1136 * 1136 + 604 * 640) / 4 = 326。默认dpr:2
逻辑像素:640 * 1136 / 2 = 320 * 568
总结
屏幕宽度dip数,即宽度px数 / dpr,都在360左右
screen.width 屏幕的dip数
window.innerWidth 浏览器的dip数(包含滚动条占据的宽度)
document.documentElement.clientWidth viewport的dip数
document.documentElement.offsetWidth 根元素的dip数
window.devicePixelRatio 屏幕dpr
orientationchange 屏幕转向事件
屏幕尺寸 = px尺寸 * px数 = dip尺寸 * dip数 = px尺寸 * dpr * dip数
视口dip数:布局宽度,即document.documentElement.clientWidth,与窗口的宽度window.innerWidth可以不同
viewport 设置
width:视口的dip数,相当一部分手机浏览器默认为 980px
deveice-width:屏幕的默认dip数,即px数 / 默认dpr
initial-scale:初始缩放比例,默认值为auto,即缩放到屏幕尺寸
user-scalable:是否允许手动缩放
mininum-scale:最小手动缩放比例
maximum-scale:最大手动缩放比例
一、桌面浏览器,设置viewport缩放,无效
二、桌面浏览器,手动缩小,就是改变dpr:
1、dpr变小,视口dip数变大
2、相对(于视口)宽度的元素,尺寸不变,dip数变大。
3、固定宽度的元素,dip数不变,尺寸变小。
4、文字无法无限缩小,缩小到一定程度后继续缩小,尺寸不变,dip数变大。
桌面浏览器的window.devicePixelRatio 与 实际dpr 相等
三、桌面浏览器,手动放大,与手动缩小效果相反
四、移动浏览器手动缩放
视口、百分比宽度元素、固定宽度元素,全都是尺寸缩放,dip数不变。视口尺寸不能缩小到比屏幕小。
四、移动浏览器,设置initial-scale放大(initial-scale大于1)
1、有些浏览器无效
2、效果与手动放大相同
五、移动浏览器,设置initial-scale缩小(initial-scale为auto或小于1)
1、实际dpr变小,视口dip数不变
2、相对(于视口)宽度的元素,dip数不变,尺寸变小。
3、固定宽度的元素,dip数不变,尺寸变小。
4、文字缩小到不能再缩小的程度
5、当视口缩小到device-width后,改为视口dip数变大(有极限),尺寸不变
自动缩小后,实际dpr与默认dpr不再相等,window.devicePixelRatio 仍然等于 默认dpr
一、未设置
默认为 width=980px,initial-scale=auto
二、viewport只设置width,不设置initial-scale
默认为 initial-scale=auto
使用场景:设计稿宽为750px(iPhone6),可以设置width=750px,自动缩放后,所有元素等比例缩小
三、viewport只设置initial-scale=1,不设置width
默认为 width=device-width
四、viewport只设置initial-scale !=1,不设置width
那么 Android width=980px,IOS width=device-width
五、viewport设置 width=device-width, initial-scale=1
那么布局宽度约为360px,这时候实际dpr 正好等于 默认dpr
viewport方案一
width=设计稿的宽度,initial-scale=auto
缺点:自动缩放,不够精细
viewport方案二
缺点:不能解决border:1px 问题
viewport方案三
初始viewport:
重设viewport:
let defaultDpr = window.devicePixelRatio || 1; // 默认dpr
let portWidth = document.documentElement.clientWidth * defaultDpr; // 物理像素数
let viewport = document.querySelector('meta[name="viewport"]');
viewport.setAttribute('content', 'width=' + portWidth + ', initial-scale=' + 1 / defaultDpr + ',user-scalable=no');
// 或者 viewport.setAttribute('content', 'width=device-width, initial-scale='+ 1 / defaultDpr + ',user-scalable=no');
// 由 上文 “缩放实践-五” 可以得出以上两行效果是一样的,效果都是 视口dip数 等于 px数
相对宽度方案
let remSize = (document.documentElement.clientWidth / 10).toFixed(2);
document.documentElement.style.fontSize = remSize + "px";
window.remSize = remSize;
window.rem2px = function(remNum) {
return parseFloat(remNum) * remSize;
};
window.px2rem: function(pxNum) {
return parseFloat(pxNum) / remSize;
};
使用vw 或 rem,rem比vw兼容性好
n倍图方案
let defaultDpr = window.devicePixelRatio || 1;
document.documentElement.setAttribute('data-dpr', window.devicePixelRatio );
window.defaultDpr = defaultDpr;
n倍图应用于默认dpr为n的屏幕,根据不同[data-dpr] 引用不同@的图片
设计稿px 转 css单位 方案
以750px设计稿为例,对应的默认dpr为2
// px 转 rem,适用于相对宽度的元素
.px2rem(@name, @px){
@{name}: @px / 75 * 1rem;
}
// px 转 px,适用于固定宽度的元素,例如字体、1px边框
// 前提为采用了 viewport方案三
.px2px(@name, @px){
@{name}: round(@px / 2) * 1px;
[data-dpr="2"] & {
@{name}: @px * 1px;
}
[data-dpr="2.5"] & {
@{name}: round(@px * 2.5 / 2) * 1px;
}
[data-dpr="2.75"] & {
@{name}: round(@px * 2.75 / 2) * 1px;
}
[data-dpr="3"] & {
@{name}: round(@px / 2 * 3) * 1px
}
[data-dpr="4"] & {
@{name}: @px * 2px;
}
}