屏幕适配

参考
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左右

JS读取屏幕信息

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

viewport 设置案例

一、未设置
默认为 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;
    }
}

你可能感兴趣的:(前端方案)