移動端使用rem適配及相關問題

移動端適配方案,說多也不少。可使用百分比佈局,但百分比與em都是基於父元素進行計算的,在實際應用中不是很方便。使用rem不只能夠設置字體大小,塊大小也能夠設置。並且能夠良好的適配各類終端,因此這方案很受歡迎。javascript

rem定義及瀏覽器支持狀況css

rem(font size of the root element)是指相對於根元素的字體大小的單位。簡單的說它就是一個相對單位。看到rem必定會想起em單位,em(font size of the element)是指相對於父元素的字體大小的單位。它們之間其實很類似,只不過一個計算的規則是依賴根元素一個是依賴父元素計算。能夠先看看rem的瀏覽器支持狀況:html

  1. Chrome 31-34 & Chrome-based Android versions (like 4.4) have a font size bug that occurs when the root element has a percentage-based size.
  2. Reportedly does not work on Android 4.3 browser for Samsung Note II or the Samsung Galaxy Tab 2 on Android 4.2.
  3. Borders sized in "rem" disappear when the page is zoomed out in Chrome.
  4. IE 9, 10 and 11 do not support rem units when used in the "line-height" property when used on :before and :after pseudo elements (https://connect.microsoft.com/IE/feedback/details/776744).
  5. Causes content display and scrolling issues on iPhone 4 which typically has Safari 5.1.

能夠看到移動端基本支持:java

ios:6.1系統以上支持;android

android:2.1系統以上都支持;ios

桌面端IE支持狀況不樂觀。web

用法:瀏覽器

現代瀏覽器,IE9+,FireFox,Safari,Chrome,Opera,默認字體是16px,設置下根元素的字體大小爲16px:app

html {
    font-size:16px;
}

,而後,若是但願某段文字的字體大小是12px,須要設置:iphone

p {
    font-size: 0.75rem; //12÷16=0.75(rem)
}

塊大小的設置是相似的,因此整個佈局的關鍵就是設置根元素的字體大小了。設置好根元素字體大小值,佈局就能夠作到自適應了。

塊大小的設置,來個例子:

設置根元素字體大小爲37.5px,在iphone6裏面須要一個寬100px的塊,就是這樣了:

<!DOCTYPE html>
<html>
    <meta charset="utf-8"></meta>
    <head>
        <title>vertical-align</title>
        <style type="text/css">
            html{
                font-size:37.5px;
            }
            #contentBox{
                width:2.667rem;
                height:2.667rem;
                background:pink;
            }
        </style>
    </head>
    <body>
        <div id="contentBox">
        </div>
    </body>
</html>

若是在iphone5下想獲得一個100px的塊,須要設置基準值(即根元素字號)爲32px。

 

下面專門談談rem的基準值設置。

rem基準值設置

想要rem適配不一樣尺寸的設備,就須要針對不一樣設備設置合適的基準值,如上例所示。

問題來了,基準值設置成多少合適?

通常拿到的設計稿是375px(2倍稿)*2的,也就是iphone6的大小。那麼對於iphone6來講,基準值能夠設置爲37.5px。即設備寬度/10。這裏作了一個除以10的計算,是由於不但願font-size值太大。這樣使用rem時值也不會太大了。

若是是iphone5,基準值就是32px。

問題又來了,如何根據設備尺寸來設置基準值?

有兩個方法,經過css media query 和js添加基準值:

css media query:

@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2){
      html{font-size: 37.5px;}
}

用media query來實現難覆蓋到全部設備:

html {
    font-size : 20px;
}
@media only screen and (min-width: 401px){
    html {
        font-size: 25px !important;
    }
}
@media only screen and (min-width: 428px){
    html {
        font-size: 26.75px !important;
    }
}
@media only screen and (min-width: 481px){
    html {
        font-size: 30px !important; 
    }
}
@media only screen and (min-width: 569px){
    html {
        font-size: 35px !important; 
    }
}
@media only screen and (min-width: 641px){
    html {
        font-size: 40px !important; 
    }
}

而經過js來設置,能夠實現覆蓋全部設備:

js來設置:

document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';

關於方案的利弊,其實上面的例子裏面能夠看出,rem爲整數的時候,基準值爲32px,36px這樣的整數,換成px也是整數。但rem帶有小數,好比1.75rem,在32px的基準只下計算得56px。那再看看其餘機型的換算值:

 

表明機型 瀏覽器寬 對應尺寸
iPhone 4/4s/5/5s 320px 56px
Samsung Note 3, Nexus 5… 360px 63px
iPhone 6 375px 65.625px
Google Nexus 6 412px 72.1px
iPhone 6 Plus 414px 72.45px

能夠看出,有些機型裏面是有小數像素值的。小數像素可能會帶來必定的偏差,設計的同事像素眼很容易覺察到的。

在能夠接受的狀況下容許這些偏差存在。在安卓機子上較多出現這類狀況。

下面能夠具體看下小數像素在瀏覽器裏面的顯示狀況:

設置兩組塊,第一組是1.75rem*1.75rem的,第二組是1.85rem*1.85rem的,具體代碼以下:

.block{
    display:inline-block;
    width:1.75rem;
    height:1.75rem;
    background:rgba(0,0,255, .5);         
}
.block:nth-of-type(2n){
    background:rgba(255,0,0, .5);
}
.group2 .block{
    widrh:1.85rem;
    height:1.85rem;
}

效果圖是

看下第一組塊,在iPhone6下,每一個塊的尺寸應該是:1.75*37.5=65.625px;

但實際狀況:

是的,瀏覽器會顯示爲65px或66px,並且沒有規律的來顯示。

這看起來有點難以想象,按道理來講,瀏覽器彷佛應該所有捨棄小數65px,或者保留到66px,可事實卻不是這樣的。

到這裏,能夠假設:瀏覽器所作的渲染處理只是做用在元素的渲染尺寸上,但他們的真實尺寸還是原始尺寸大小。

舉個實際的例子來講,就是一個元素的尺寸是0.625px,他的渲染尺寸是1px,剩下的0.375px由臨近元素填充;同理,若是一個元素是0.375px,其渲染尺寸是0px,可是會佔有臨近元素0.375px的空間。

而後帶着這個假設分析下上面的例子:
    第一個塊的寬度爲 65.625px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.375px 由第二個塊補上;
    第二個塊向左補進 0.375px,至關於減小了 0.375px,餘下 65.25px,根據四捨五入的原則其最終渲染尺寸爲 65px,多出的 0.25px 會佔用第三個色的空間;
    第三個塊被佔用了 0.25px,至關於增長了 0.25px,等於 65.875px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.125px 由第四個塊補上;
    第四個塊向左補進 0.125px,至關於減小了 0.125px,餘下 65.5px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.5px 由第五個塊補上;
    第五個塊向左補進 0.5px,至關於減小了 0.5px,餘下 65.125px,根據四捨五入的原則其最終渲染尺寸爲 65px,多出 0.125px;
這與瀏覽器的輸出結果是一致的,印證了猜測。

更具體的瀏覽器處理能夠看http://trac.webkit.org/wiki/LayoutUnit

其餘適配方案

也能夠採用固定佈局:

1.在viewport meta標籤上設置width=320,頁面的各個元素也採用px做爲單位。經過用JS動態修改標籤的initial-scale使得頁面等比縮放,從而恰好佔滿整個屏幕。

<meta name="viewport" content="width=320,user-scalable=no">

2.rem也可使用本身設置viewport和content的方法來適配,以方便計算和設置值:

例如:

meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');

其中dpr經過window.devicePixelRatio獲取,iphone6的值是2.

對於2倍稿,能夠直接設置基準值爲2倍,這樣就不用設計稿的值除以2了。

iphone6適配的設計稿750px,基準值設置爲75px就能夠了。

修改了縮放倍數以後,1px邊線的問題也同時解決了。

代碼:

<!DOCTYPE html>
<html>
    <meta charset="utf-8"></meta>
    <meta name="viewport" content="" id="viewMeta">
    <head>
        <title>vertical-align</title>
        <style type="text/css">
            html{
                font-size:75px;
            }
            #contentBox{
                width:2.667rem;
                height:2.667rem;
                background:pink;
                border:1px solid #000;
            }
        </style>
    </head>
    <body>
        <div id="contentBox">
        </div>
    </body>
    <script type="text/javascript">
    var meta = document.getElementById('viewMeta');
    var dpr = window.devicePixelRatio;
    meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
    </script>
</html>

圖圖:

 

參考:

http://www.alloyteam.com/2016/03/mobile-web-adaptation-tool-rem/?utm_source=tuicool&utm_medium=referral#prettyPhoto

相關文章
相關標籤/搜索