作移動端頁面以來,常常會據說移動端的適配這個問題,可是並無認真分析過是如何適配各類機型的。目前公司用的是手淘的flexible.js進行頁面適配的。適配的根本原理其實就是將設計稿按必定的比例在不一樣的手機上實現。javascript
在分析移動段適配以前首先要了解一下rem, css3的一個相對長度單位。既然是相對長度,那就有一個參照體了,rem就是相對於html元素的font-size計算值的倍數。即1rem 等於一倍的html元素的font-size值。css
最先看到這個適配是在同事的代碼裏,當時並不知到是什麼原理,也並不明白這些數字是怎麼來的。
@media screen and (min-width:350px){ html{font-size:342%;} } @media screen and (min-width:360px){ html{font-size:351.56%;} } @media screen and (min-width:375px){ html{font-size:366.2%;} } @media screen and (min-width:384px){ html{font-size:375%;} } @media screen and (min-width:390px){ html{font-size:380.85%;} } @media screen and (min-width:393px){ /* 小米NOTE */ html{font-size:383.79%;} } @media screen and (min-width:410px){ html{font-size:400%;} } @media screen and (min-width:432px){ /* 魅族3 */ html{font-size:421.875%;} } @media screen and (min-width:480px){ html{font-size:469%;} } @media screen and (min-width:540px){ html{font-size:527.34%;} } @media screen and (min-width:640px){ html{font-size: 625%;} } @media screen and (width:720px){ html{font-size: 703.125%;} }
@media
媒體查詢, 能夠針對不一樣的屏幕尺寸設置不一樣的樣式,特別是若是你須要設置設計響應式的頁面,@media 是很是有用的。當你重置瀏覽器大小的過程當中,頁面也會根據瀏覽器的寬度和高度從新渲染頁面。
上述代碼中,第一個@media screen and (min-width:350px)
表示當移動設備的寬度大於350px的時候頁面將使用花括號內的樣式,即將html根元素的字號設置爲342%。(max-width:350px,則表示設備寬度小於350px時將採用此樣式)。上述css代碼的做用可見就是在不一樣分辨率的設備上設置不一樣的html字體大小。html
爲何要這樣設置呢?由於這種適配方法用的是css3的rem來進行適配的,而前面講了,rem是相對於html的字號來計算的,如今不一樣的設備上html的字號改變了,也就意味這1rem表明的px像素值不一樣了,也就達到了按比例在不一樣設備上適配同一個頁面的效果了。java
html元素的font-size值又是怎麼肯定的呢?拿下面的舉例:css3
@media screen and (min-width:375px){ html{font-size:366.2%;} }
屏幕寬度大於375px的會按照寬度375px來適配。設計同時平時給咱們的設計稿通常是640px寬度或者750px寬度的,而咱們上面的都是假定設計稿是640px寬來計算的,750px也是同理計算。如今:web
1.屏幕寬度是375,設計稿寬度是640,ratio = 375/640=0.5859375;
2.咱們要將設計稿上元素用css單位rem寫下來,那麼該如何轉換,1rem應該等於稿子上多少px。
這裏咱們設定1rem = 100px ;能夠設定其它值嗎,固然能夠,這裏設置爲100只是方便咱們在寫css的時候好計算,小數點直接左移兩位就能夠了。好比,設計稿上一個寬46px按鈕,這樣轉換成rem直接就是0.46rem。
3.如今1rem表明設計稿上100px,那麼又該是等於設備上最後真實的多少像素呢。就要用到前面的屏幕寬度和設計稿的寬度比 ratio,設計稿上100px表明了真實的設備100*ratio = 58.59375px。
換句話說 css中寫的1rem等於設備58.59375px。又由於1rem等於1倍的html元素的font-size,因此這裏的html元素的font-size最終應該設置成58.59375px。可爲何上述代碼中用的是百分比呢?由於通常瀏覽器中html元素的默認字號都是16px,可是當用戶放大或者縮小瀏覽器字號設置時,就不會是16px了,因此咱們將html的font-size仍是設置成百分比更好,即 58.59375/16= 366.2109375%,也就是上面例子中的366.2%了。segmentfault
其它的屏幕上也是同此道理計算出html的font-size值的。瀏覽器
@media + rem適配移動端還有一個不可少的條件就是要在head標籤中寫入一個meta標籤。 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1">
;關於viewport的瞭解能夠看這裏。此標籤的做用是讓layout viewport = visual viewport,用戶也不可縮放頁面。app
flexible.js也是rem適配的,它是將設備分紅10份,1rem等於1/10。分析其中部分代碼:字體
var devicePixelRatio = win.devicePixelRatio; dpr = devicePixelRatio || 1; if (isIPhone) { // iOS下,對於2和3的屏,用2倍的方案,其他的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其餘設備下,仍舊使用1倍的方案 dpr = 1; } scale = 1 / dpr; ...... ....... metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
win.devicePixelRatio
(簡稱dpr),即設備像素比(戳我瞭解)
上述代碼當dpr(設備物理像素和設備獨立像素比)爲3時候,頁面縮入1/3,dpr爲2時,頁面綻開2/1。
function refreshRem(){ var width = docEl.getBoundingClientRect().width; if (width / dpr > 750) { width = 750 * dpr; } var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; }
上述代碼將1rem設置成了設備真實寬度的1/10,所以html根元素的fontSize也就是設備真實寬度的1/10,假如設計老鐵們給的漂亮稿子是750px寬的,寫scss時1rem也就應該等於75px,那邊我麼的scss文件能夠這樣寫:
@function px2rem($px, $base: 75) { @return ($px / $base) * 1rem; } /* 稿子上量得某按鈕寬60px,高20px */ .btn{ width:px2rem(60); height:px2rem(20); }
vw:viewport width(可視窗口寬度)
vh:viewport height(可視窗口高度)
vw和vh等詳情能夠點這裏
1vw等於1%的設備寬度(設計稿寬度),1vh等於1%的設備高度(設計稿高度),這樣看來vw,vh其它是最方便的,可是目前兼容性不是特別好。
因此只有在不須要考慮兼容的時候能夠用這個相對最簡便的適配方案了,好比一些混合開發裏,app內的瀏覽器若是支持vw、vh,只在app內使用的頁面就能夠放心大膽的用了。像下面的
客戶端內的右下角webview,一個小的PK對決頁面,這裏就是用的vw,vh進行適配的。
/*右下角窗口設計稿寬200px,高220px*/ @function px2vw($px, $base: 200) { @return ($px/($base/100)) + vw; } @function px2vh($px, $base: 220) { @return ($px/($base/100)) + vh; } /*頭像寬42px,高42px*/ .avantar{ width:px2vw(42); heightx:px2vh(42); }
目前工做中用到的就是後面的兩種適配方案了。手淘那個還有的地方看不懂,仍是本身太Low了,可是看不懂車不影響老司機開車。