移動端適配 後篇(rem+vm)

涉及到的一些名詞, 詳細解釋可參考 移動端適配前篇--移動端適配 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 * 1136dom

前提:假如以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>

手淘:可以使用 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-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>

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佈局
移動前端自適應適配佈局解決方案和比較

相關文章
相關標籤/搜索