涉及到的一些名词, 详细解释可参考 移动端适配前篇--移动端适配 remcss
【英寸Inch】英寸表示屏幕斜对角线的长度
【像素Pixel】像素是图像的基本采样单位,它不是一个肯定的物理量,由于像素点的物理大小是不肯定的
【分辨率】分辨率是屏幕像素的数量,通常用屏幕宽度的像素点乘以屏幕高度的像素点。如描述iphone6的分辨率是750*1334
.
分辨率又分为【物理分辨率】和【逻辑分辨率】,值得注意的是实际工做中设计师经常给的是物理分辨率,程序中用到的是逻辑分辨率,可是都称为分辨率,容易混淆。
【物理分辨率】是硬件所支持的分辨率,【逻辑分辨率】是软件能够达到的分辨率。
【像素倍率dpr】物理分辨率和逻辑分辨率的商,即常说的几倍屏。html
如:iphone6的分辨率写着375*667
,指的是逻辑分辨率;750*1334
则是它的物理分辨率,dpr=2。前端
使用rem适配,目前最流行的两种方式:分别是网易和手淘的作法git
设备逻辑像素 device-width = 设备物理像素 /(devicePixelRatio * scale)
设备物理像素: iphone6 = 750px
设备逻辑像素: iphone6 = 750/(2 * 1) = 375px
document.documentElement.clientWidth === 设备逻辑像素
body-width(rem为单位) = 设计稿宽度/100 = 640 / 100 = 6.4 rem 【取100,主要为了容易计算】
html font-size(px为单位) = device-width / body-width = 320 / 6.4 = 50 pxgithub
【步骤】
(1)视口设置:<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, minimum-scale=1">
(2)先拿设计稿竖着的横向分辨率除以100获得body元素的宽度:
若是设计稿基于iphone6,横向分辨率为750,body的width为750 / 100 = 7.5rem
若是设计稿基于iphone4/5,横向分辨率为640,body的width为640 / 100 = 6.4rem
(3)布局时,设计图标注的尺寸除以100获得css中的尺寸
设计稿150px的宽度,代码为 150/100 rem
(4)在dom ready之后,经过如下代码设置html的font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
【html的font-size的值 是根据设备改变而改变的】
(注:6.4是设计稿基于iphone4/5,若是是750的设计稿,应该除以7.5)
(5)font-size可能须要额外的媒介查询,而且font-size不能使用rem【此处的px是指设备逻辑像素】segmentfault
@media screen and (max-width:321px){ .m-navlist{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .m-navlist{font-size:16px} } @media screen and (min-width:400px){ .m-navlist{font-size:18px} }
【注意】最大宽度限制 设备逻辑像素宽度640 =》设备物理像素宽度1280 至关于pc端
var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth > 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px'; 【此处6.4,因为网易以iPhone4/5,物理像素为640 * 1136
】dom
前提:假如以iPhone6/7/8为设计稿,宽度为150的元素 在 iphone6/7/8中: 因为【dpr = 2】,该元素的逻辑像素 = 150 / 2 = 75 px html-fontSize = 375 / 7.5 = 50 px 该元素的 width = 150 / 100 = 1.5 rem 该元素的逻辑像素 / html-fontSize = 75 / 50 = 1.5 在iPhone4/5中:【逆推】 在 iphone4/5中,html-fontSize = 320 / 7.5 = 42.67 px 该元素的 width = 1.5 rem 该元素的逻辑像素 = html-fontSize * 该元素的 width(rem) = 42.67 * 1.5 = 64 px 因为【dpr = 2】,该元素的物理像素 = 逻辑像素 * dpr = 64 * 2 = 128 (即该元素的宽为128) 该元素的逻辑像素 / html-fontSize = 64 / 42.67 = 1.5 **总结: 64/320 = 75/375 = 0.2 至关于百分比适配,该元素占整屏宽度的20%**
demo:iphone
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>移动端适配</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/> <style> /* vw + rem */ html{font-size:13.33333333vw} .box { width: 1.5rem; height: 1.5rem; background-color: #ccc; font-size: 0.24rem; } /* rem 网易*/ .box { width: 1.5rem; height: 1.5rem; background-color: #ccc; font-size: 14px; } /*逻辑像素*/ @media screen and (max-width:321px){ .box{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .box{font-size:16px} } @media screen and (min-width:400px){ .box{font-size:18px} } </style> <script> window.onload = function () { var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 640) deviceWidth = 640; document.documentElement.style.fontSize = deviceWidth / 7.5 + 'px'; } </script> </head> <body> <div class="box"> oooo </div> </body> </html>
(1)动态设置viewport的scale布局
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
(2)动态计算html的font-sizeflex
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
(3)布局的时候,各元素的css尺寸 = 设计稿标注尺寸/(设计稿横向分辨率 / 10)
(4)font-size可能须要额外的媒介查询,而且font-size不使用rem,这一点跟网易是同样的。
总结:
设备逻辑像素 device-width = 设备物理像素 /(devicePixelRatio * scale) 因为 scale = 1 / devicePixelRatio,因此【设备逻辑像素 = 设备物理像素】
前提:假如以iPhone6/7/8为设计稿,宽度为150的元素 在 iphone6/7/8中: 设备逻辑像素 = 750 /(`2*0.5`) = 750 px 因为【dpr = 2】,该元素的逻辑像素 = 150 /(`2*0.5`) = 150 px html-fontSize = 750 / 10 = 75 px 该元素的 width(rem) = 150 / html-fontSize = 150 / 75 = 2 rem 在iPhone4/5中:【逆推】 在 iphone4/5中,html-fontSize = 640 / 10 = 64 px 该元素的 width = 2 rem 该元素的逻辑像素 = html-fontSize * 该元素的 width(rem) = 64 * 2 = 128 px => 150 / 750 = 128 / 640 = 0.2
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
demo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>移动端适配</title> <!-- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/> --> <meta name="viewport"/> <style> .box { width: 2rem; height: 2rem; background-color: #ccc; font-size: 14px; } /*逻辑像素*/ @media screen and (max-width:321px){ .box{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .box{font-size:16px} } @media screen and (min-width:400px){ .box{font-size:18px} } </style> <script> window.onload = function () { var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); // console.log(document.documentElement.clientWidth) // 750 = 750 / (2 * 0.5) // 设备逻辑像素 device-width = 设备物理像素 /(devicePixelRatio * scale) document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; } </script> </head> <body> <div class="box"> oooo </div> </body> </html>
html{font-size:13.33333333vw} <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
1vw表示1%的屏幕宽度, 即屏幕宽度被分为100份vw
width:1rem 的div 就是50px* 50px (iphone6为2倍屏,即对应750px设计稿上的100px*100px)
7.5 rem = 100vw = 750px 设计稿 =》1px = 0.1333333vw =》 100px = 13.33333vw => 100px = 1rem
以iPhone6/7/8为设计稿标准, 宽度为 180 px
该元素的宽度(rem)= 180 / 100 = 1.8 rem
布局时各元素的尺寸值都是根据设计稿标注的尺寸计算出来,因为html的font-size是动态调整的,因此可以作到不一样分辨率下页面布局呈现等比变化
通过正反推算,发现各类单位适配本质上对应着仍是根据手机屏幕尺寸基于百分比
进行缩放
参考:
最简单的移动端适配方案(rem+vw)
移动端(手机端)页面自适应解决方案—rem布局
移动前端自适应适配布局解决方案和比较