用rem適配移動端

常見方式:

1. 固定寬度(320)作法:這樣前端卻是爽了,但是大頁面兩邊有留白,小頁面圖標文字又會縮的很小,用戶體驗極其很差。css

2. 流式佈局:其實就是用%,這樣寬度倒還差很少,高度怎麼搞?因此這種佈局通常都是寬度自適應高度寫死,顯的很不協調,另外對設計也有很大的限制,另外還有兼容性方面的問題。html

3. 響應式佈局:說白了就是利用CSS3中的Media Query(媒介查詢),喊的很火,誰用誰知道,簡直累死人不要命。前端

4. 設置viewport進行縮放:以320寬度爲基準,進行縮放,最大縮放爲320*1.3 = 416,基本縮放到416都就能夠兼容iphone6 plus的屏幕了。<meta name="viewport" content="width=320,maximum-scale=1.3,user-scalable=no">git

5. 利用vh、vw適配:兼容性太差。github

rem是什麼

rem是一個相對根元素html字體大小的單位,因此它的大小是由html的fontSize大小決定的,假如我把html的fontSize設置爲10px,此時的1rem就等於10px,假如我把html的fontSize設置爲100px,此時的1rem就等於100px,這也正是咱們能用rem作移動端適配的根本緣由,就是經過不一樣屏幕下改變根元素fontSize的大小,從而讓以rem爲單位的各類元素自動隨着改變。web

適配標準

經過下面這句話得到理想視口(ideal viewport):chrome

<meta name="viewport" content="width=device-width">

既然要適配,就要選一個理想視口作基準,而後才能在此基礎上等比縮放(這裏等比縮放最好不包括文字,後面講緣由),咱們通常選擇iphone6的375,爲何選它呢?瀏覽器

由於市場上的Android機五花八門(理想視口寬通常在320-480之間),且沒有任何一款的佔有率能和iphone相比,選取iphone中的iphone6能更好的向下適配iphone5和向上適配iphone6 plus等,關於各機型的理想視口(ideal viewport)詳見VIEWPORT SIZESsass

設計圖

上面說了咱們要以iphone6爲基準,那麼設計圖咱們作成多大呢?dom

設計圖作成750px寬,由於iphone6的物理像素是750(上面咱們說的375是它的設備獨立像素,又是理想視口),咱們要想作到高清就要1個設計像素對應一個物理像素才成,他們之間的關係見下表:

  iPhone6 plus iPhone6 iPhone5
物理像素(physical pixel) 看公式 看公式 看公式
設備獨立像素(density-independent pixel) 414x736 375×667 320x568
設備像素比(device pixel ratio ) 3 2 2

設備像素比(dpr),咱們能夠經過JavaScript獲取的辦法是:window.devicePixelRatio;用CSS獲取的辦法是-webkit-device-pixel-ratio。咱們能夠用-webkit-min-device-pixel-ratio-webkit-max-device-pixel-ratio進行媒體查詢,以達到適配不一樣dpr的需求。

用CSS適配

原理:用媒體查詢理想視口(上面咱們把width=device-width了,因此查詢width便可),不一樣理想視口設置不一樣的根元素fontSize。

一張750的設計稿,假如其根元素爲100px(爲何是100px而不是其餘的呢?),此時我想表示一個750px*100px的div,我只須要寫成:

div{width:7.5rem; height:1rem;}

那麼問題來了,我在iphone6下把根元素字體設爲多大才能讓這個div等比顯示呢?要想等比顯示那麼他們之間有這樣一個關係:

100px / 750 = iphone6 根元素fontSize / iphone6理想視寬(375)

根據上面公式算出iphone6 根元素fontSize = 50px,也就是在iphone6下咱們只須要改變根元素fontSize爲50px就能夠作到等比縮放啦~~

那麼問題又來了,手機那麼多,各類機型的理想寬度也數不勝數(其實大多都在320到480之間,上面有說),那麼其對應根元素fontSize我該怎麼寫呢?

做爲一個CSSer,咱們最早想到的是媒體斷點查詢,例如像下面這樣:

@media screen and (min-width:321px) and (max-width:375px){
  html{font-size:42px}
}
@media screen and (min-width:376px) and (max-width:414px){
  html{font-size:50px}
}
@media screen and (min-width:415px) and (max-width:639px){
  html{font-size:55px}
}
@media screen and (min-width:640px) and (max-width:719px){
  html{font-size:85px}
}
@media screen and (min-width:720px) and (max-width:749px){
  html{font-size:95x}
}
@media screen and (min-width:750px) and (max-width:800px){
  html{font-size:100px}
}

上面的缺點一目瞭然,就是不夠精細嘛,例如415-639理想視寬的手機顯示的東西倒是同樣大,對於像素級要求的咱們這怎麼能成呢?

因而乎我用sass把從320到750所有算一遍不就能夠啦,就像下面這樣:

@media (max-width: 320px){
  html{ font-size: 266.66667%; }
}
@for $i from 320 through 750 {@media (width:#{$i}px){
  html{font-size: $i/1.2 * 1%}}
}
@media (min-width: 750px){
  html{ font-size: 625%; }
}

Sass生成結果(景象過於壯觀慎入),大功告成,這樣咱們不用JavaScript也能實現和其同樣的精細效果了。使用時只需在頭部引用這樣一個CSS文件便可,假如750上你量出的div大小爲width:85px;height:100px;,寫的時候只需除以100便可,即width:.85rem;height:1rem;你要嫌除的麻煩sublime中能夠裝這麼一個轉換插件

這時確定會有人吐槽性能問題洛,壓縮後的media100px.css大概10幾kb的樣子,我看了下我們移動網站的一個普通商品圖大概是它的2倍,固然拿兩個東西進行比較是有點不太穩當,具體增長這麼些樣式會影響多大性能暫未驗證。

之因此在750下把根元素設爲100而不是其餘,是由於方便計算嘛,1rem等於100px,.2rem就等與20px這樣多好算啊,有人會問你丫設爲10不同好算啊,話說通常瀏覽器顯示的最小字號是12px,因此就100啦,固然數學好的你用其餘值也是能夠的。

上面用Sass生成的css根元素字體大小我是用%號表示的,就是100px,我寫的是625%,有人可能會問你這幹嗎畫蛇添足呢,625%不就是100px嘛,有人給出了下面幾個理由,我抄下來共你們參考:

  • 某些設備的默認字體大必定是16px,特別是高分辨率的設備,設置成百分比能夠按照設備的基準字體大小給編寫的網頁設置好最適合用戶瀏覽的字體大小。
  • 這樣寫是兼容將來趨勢的綜合考慮,px這個單位的含義已經愈來愈混亂,幾乎沒法評估之後的設備是會像如今這樣對網頁上的px作兼容處理,但用百分比表明默認字體尺寸基本不會混亂。

用JavaScript適配

上面直接引用直接media100px.css的確不是最好的方案,你知道我要說什麼啦,那就是用JavaScript適配,其實咱們把上面的Sass循環改爲用JS寫就行了,就像下面這樣:

!(function(doc, win) {
  var docEle = doc.documentElement,
  evt = "onorientationchange" in window ? "orientationchange" : "resize",//區分Mobile和PC以加載不一樣的事件
  fn = function() {
    var width = docEle.clientWidth;
    if( width < 320 ) {
      docEle.style.fontSize = 42.6667 + "px";
    }
    else if( width > 750 ) {
      docEle.style.fontSize = 100 + "px";
    }
    else {
      //以750設計稿寬度爲基準設置fontSize:100px;這樣保證iPhone6如下是高清
      docEle.style.fontSize = 100 * (width / 750) + "px";
    }
  };
  win.addEventListener(evt, fn, false);
  //load事件是在頁面全部元素都加載完後觸發;
  //DOMContentLoaded,它是指dom tree加載完就觸發,頁面引用的樣式表和圖像文件可能尚未加載完成
  doc.addEventListener("DOMContentLoaded", fn, false);
}(document, window));

在使用的時候你能夠單獨引用這樣一段JS (看上面我又不用%而用px啦,測試(chrome模擬手機測試的)後發現%和px最終造成網頁效果並沒有差異),不使用不引用便可;或者把這段JS放在公共JS文件裏,而對於不想使用rem的同窗只需覆蓋JS設置的樣式便可,例如像下面這樣:

html{font-size:20px!important;}//這裏移動端默認字體大小根據狀況本身設置

注意事項

1.文字最好不要用rem表示,由於:

其一:設計師通常但願是文字在移動設備上的顯示大小是同樣的,也就是咱們所說的等比適配(注意是等比適配不包括,不是適配)是不該包括文字的;

其二:咱們用rem後文字會很小(雖然這正是等比縮放的結果),固然這也和設計有關(理論上字體須要等比適配的話750px設計圖上是不該該有小於24px字體出現的,既然有也說明字體不該該等比適配),例如我在設計圖上量取的文字大小是24px,那麼其iphone6下的顯示大小就是.24rem*50=12px,而設計圖上哪些24如下的字體此時也會顯示12px(假如最小字體是12的話),這也會有另一個問題,就是設計圖上明明是不一樣字體大小表示的文案,在手機上顯示的大小倒是同樣的,起不到設計師想要表達的區分或者強調的做用;

其三:網上有說會變模糊之類的,我暫時未發現(暴漏了我依然表示字體用rem表示的...)。

解決辦法:能夠分斷點區間,設置不一樣的fontSize大小,能夠參考點我

2.1px和2px不要寫成.01rem和.02rem,由於:

以750適配的方案爲例,當理想視口爲320時,其對應font-size: 266.66667%; 而後乘以默認字體大小16px,最後爲42.6666672px,也就是43px,若寫爲.01rem或.02rem表示分別對應.42px或.96px,在直接取整的瀏覽器下是顯示不出來的。因此對於1像素邊框的就不要寫.01rem啦。

3.當咱們寫1px時,實際在dpr爲2的手機下顯示的是2個物理像素,看起來會粗一點,解決方案能夠參照淘寶的flexible,其原理是根據dpr的不一樣動態設置initial-scale的值,也能夠用下面方法實現:

.scale {   position: relative;   height: 50px;   line-height: 50px;   background-color: #ccc;
} .scale:after {   position: absolute;   content: '';   width: 100%;   left: 0;   bottom: 0;   height: 1px;   background-color: red;   -webkit-transform: scale(1,.5);   transform: scale(1,.5);   -webkit-transform-origin: center bottom;   transform-origin: center bottom;
}

注:JavaScript適配方案是一種思路或者中心思想,在實際使用中會有其餘一些問題須要注意,例如JS的加載時機以及其餘有一些安卓機的奇怪問題,具體能夠參考淘寶的flexible解決方法,或者參考咱們目前在用的方案:flexible精簡版下載

相關文章參考:

白色橡樹的整理

移動前端開發之viewport的深刻理解

移動端高清、多屏適配方案

 

以上文字友好閱讀方式:點我下載

相關文章
相關標籤/搜索