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


移動端適配方案,說多也很多。可以使用百分比布局,但百分比與em都是基於父元素進行計算的,在實際應用中不是很方便。使用rem不僅可以設置字體大小,塊大小也可以設置。而且可以良好的適配各種終端,所以這方案很受歡迎。

rem定義及瀏覽器支持情況

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

  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.

可以看到移動端基本支持:

ios:6.1系統以上支持;

android:2.1系統以上都支持;

桌面端IE支持情況不樂觀。

用法:

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

html {
    font-size:16px;
}

,然后,如果希望某段文字的字體大小是12px,需要設置:

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM