涉及到的一些名詞, 詳細解釋可參考 移動端適配前篇--移動端適配 rem
名詞解釋
【英寸Inch】英寸表示屏幕斜對角線的長度
【像素Pixel】像素是圖像的基本采樣單位,它不是一個確定的物理量,因為像素點的物理大小是不確定的
【分辨率】分辨率是屏幕像素的數量,一般用屏幕寬度的像素點乘以屏幕高度的像素點。如描述iphone6的分辨率是750*1334
.
分辨率又分為【物理分辨率】和【邏輯分辨率】,值得注意的是實際工作中設計師常常給的是物理分辨率,程序中用到的是邏輯分辨率,但是都稱為分辨率,容易混淆。
【物理分辨率】是硬件所支持的分辨率,【邏輯分辨率】是軟件可以達到的分辨率。
【像素倍率dpr】物理分辨率和邏輯分辨率的商,即常說的幾倍屏。
如:iphone6的分辨率寫着375*667
,指的是邏輯分辨率;750*1334
則是它的物理分辨率,dpr=2。
使用rem適配,目前最流行的兩種方式:分別是網易和手淘的做法
網易
設備邏輯像素 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 px
【步驟】
(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是指設備邏輯像素】
@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
】
前提:假如以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:
<!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>
手淘:可使用 lib-flexible
(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-size
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>
vw + rem
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布局
移動前端自適應適配布局解決方案和比較