前言:這周工作碰到了移動(dòng)端1px的問題彩届。以前一直寫樣式也沒有特別注意著一點(diǎn)渐裂。還有就是rem的原理繁疤。這些其實(shí)就是比較常見的移動(dòng)端適配問題。現(xiàn)階段比較主流的適配方案有二種揣炕。一種是
flexible + rem
,另一種是vw
下面我們來看一下具體情況
1帘皿、基本概念
在了解具體方案原理前,我們先來看一下一些基本概念:
1.1畸陡、物理像素(physical pixel)
物理像素又被稱為設(shè)備像素鹰溜,他是顯示設(shè)備中一個(gè)最微小的物理部件。每個(gè)像素可以根據(jù)操作系統(tǒng)設(shè)置自己的顏色和亮度丁恭。
1.2曹动、設(shè)備獨(dú)立像素(density-independent pixel)
設(shè)備獨(dú)立像素也稱為密度無關(guān)像素,可以認(rèn)為是計(jì)算機(jī)坐標(biāo)系統(tǒng)中的一個(gè)點(diǎn)牲览,這個(gè)點(diǎn)代表一個(gè)可以由程序使用的虛擬像素(比如說CSS像素)墓陈,然后由相關(guān)系統(tǒng)轉(zhuǎn)換為物理像素。(老早在沒有 retina 屏之前第献,設(shè)備獨(dú)立像素與物理像素是相等的)
1.3跛蛋、CSS像素
CSS像素是一個(gè)抽像的單位,主要使用在瀏覽器上痊硕,用來精確度量Web頁面上的內(nèi)容赊级。一般情況之下,CSS像素稱為與設(shè)備無關(guān)的像素(device-independent pixel)岔绸,簡稱DIPs理逊。
1.4橡伞、設(shè)備像素比(device pixel ratio)
設(shè)備像素比簡稱為dpr,其定義了物理像素和設(shè)備獨(dú)立像素的對應(yīng)關(guān)系晋被。它的值可以按下面的公式計(jì)算得到:
設(shè)備像素比 = 物理像素 / 設(shè)備獨(dú)立像素
在JavaScript
中兑徘,可以通過window.devicePixelRatio
獲取到當(dāng)前設(shè)備的dpr
。而在CSS中羡洛,可以通過-webkit-device-pixel-ratio
挂脑,-webkit-min-device-pixel-ratio
和 -webkit-max-device-pixel-ratio
進(jìn)行媒體查詢,對不同dpr
的設(shè)備欲侮,做一些樣式適配(這里只針對webkit內(nèi)核的瀏覽器和webview)
因此在iphone 6崭闲、7、8 的 dpr 為 2的設(shè)備中威蕉,一個(gè)設(shè)備獨(dú)立像素便為 4 個(gè)物理像素刁俭,因此在 css 上設(shè)置的 1px 在其屏幕上占據(jù)的是 2個(gè)物理像素,0.5px 對應(yīng)的才是其所能展示的最小單位韧涨。
1.5牍戚、rem
簡單的理解,rem
就是相對于根元素<html>
的font-size
來做計(jì)算虑粥。而我們的方案中使用rem
單位如孝,是能輕易的根據(jù)<html>
的ont-size
計(jì)算出元素的盒模型大小。而這個(gè)特色對我們來說是特別的有益處娩贷。
2第晰、flexible實(shí)現(xiàn)方案
了解了前面一些相關(guān)概念之后,接下來我們來看實(shí)際解決方案育勺。淘寶有一個(gè)名叫lib-flexible的庫,而這個(gè)庫就是用來解決H5頁面終端適配的罗岖。
我們把屏幕分成10等分涧至,那么
- 物理像素為 750 = 375 * 2,那么 10rem = 750px桑包,1rem = 75px;
- 物理像素為 1125 = 375 * 3南蓬,那么 10rem = 1125px,1rem = 112.5px ;
- 物理像素為 1242 = 414 * 3, 那么 10rem = 1242px哑了,1rem = 124.2px;
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
2.1赘方、1px的物理像素的解決方案
由此我們得到一個(gè)1px像素的解決方案。viewport 的 initial-scale 具有縮放頁面的效果弱左。對于 dpr=2 的屏幕窄陡,1px壓縮一半便可與1px的設(shè)備像素比匹配,這就可以通過將縮放比 initial-scale 設(shè)置為 0.5=1/2 而實(shí)現(xiàn)拆火。以此類推 dpr=3的屏幕可以將 initial-scale設(shè)置為 0.33=1/3 來實(shí)現(xiàn)跳夭。
<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5">
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
3涂圆、視口單位適配方案
將視口寬度 window.innerWidth 和視口高度 window.innerHeight 等分為 100 份,且將這里的視口理解成 idealviewport 更為貼切币叹,并不會(huì)隨著 viewport 的不同設(shè)置而改變润歉。
1、vw : 1vw 為視口寬度的 1%
2颈抚、vh : 1vh 為視口高度的 1%
3踩衩、vmin : vw 和 vh 中的較小值
4、vmax : 選取 vw 和 vh 中的較大值
如果設(shè)計(jì)稿為 750px贩汉,那么 1vw = 7.5px驱富,100vw = 750px。其實(shí)設(shè)計(jì)稿按照設(shè)么都沒多大關(guān)系雾鬼,最終轉(zhuǎn)化過來的都是相對單位萌朱,上面講的 rem 也是對它的模擬。
跟之前一樣的痛點(diǎn)策菜,我們?nèi)匀恍枰ㄙM(fèi)大量不必要的計(jì)算時(shí)間去把標(biāo)注圖中的px轉(zhuǎn)換為vw晶疼,有沒有類似于postcss-px2rem的工具呢?很榮幸能再次站在巨人的肩膀上又憨,已經(jīng)有大神寫了了類似的PostCss插件 postcss-px-to-viewport
參看資料
https://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html