移動(dòng)端適配之rem

現(xiàn)在的移動(dòng)設(shè)備種類(lèi)繁多,導(dǎo)致需要針對(duì)不同的尺寸進(jìn)行適配。
可以使用媒體查詢(xún)的方式,但是媒體查詢(xún)的方式因?yàn)橛锌缍?與dpr的不同所以會(huì)有誤差。

html{font-size:10px}
@media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}}
@media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}}
@media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}}
@media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}}
@media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}}
@media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}}
@media screen and (min-width:800px){html{font-size:25px}}

本文主要講的不是媒體查詢(xún)的方式,主要是根據(jù)dpr計(jì)算得到font-size的值。
下面的iphone的尺寸表格

設(shè)備尺寸.png

設(shè)備具有邏輯分辨率和設(shè)備分辨率,
設(shè)備像素比(dpr)= 設(shè)備分辨率/邏輯分辨率
dpr越大說(shuō)明越清晰,因?yàn)樗茱@示的基本單位更小

對(duì)比圖.png

移動(dòng)端適配的話,我們使用的單位是rem,所以需要根據(jù)不同的設(shè)備和不同的dpr計(jì)算出rem的基準(zhǔn)值。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <!--這一句話一定要先寫(xiě)上,然后再通過(guò)js修改,不然clientWidth不對(duì)-->
  <meta content='width=device-width,initial-scale=1' name="viewport" />
  <title>css</title>
  <style>
    div{
      border: 1px solid red;
      width: 5rem;
    }
  </style>
</head>

<body>
  <div id='my-element'></div>
  <script>
      (function(){
  var dpr, rem, scale;
  var docEl = document.documentElement;
  var fontEl = document.createElement('style');
  var metaEl = document.querySelector('meta[name="viewport"]');

  dpr = window.devicePixelRatio || 1;
  rem = docEl.clientWidth * dpr / 10;
  scale = 1 / dpr;

  // 設(shè)置viewport,進(jìn)行縮放,達(dá)到高清效果
  metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');

  // 設(shè)置data-dpr屬性,留作的css hack之用
  docEl.setAttribute('data-dpr', dpr);

  // 動(dòng)態(tài)寫(xiě)入樣式
  docEl.firstElementChild.appendChild(fontEl);
  fontEl.innerHTML = 'html{font-size:' + rem + 'px !important;}';
})()
  </script>
</body>
</html>

實(shí)踐:
一般情況下,UI出的圖都是按照設(shè)備分辨率出的圖,比如我們拿到的設(shè)計(jì)圖的視覺(jué)稿是按照iphone7來(lái)設(shè)計(jì)的,也就是750*1334 dpr=2
所以根據(jù)上面的方法rem = docEl.clientWidth * dpr / 10; 可以得到rem=75,有必要說(shuō)明一下clientWidth指的是邏輯分辨率的寬度,

實(shí)踐延伸
但是當(dāng)你在初始頁(yè)面設(shè)置了initial-scale后,clientWidth和初始的時(shí)候不一樣,比如initial-scale=0.5,clientWidth會(huì)變成750(375/0.5),所以有必要初始的時(shí)候設(shè)置initial-scale=1

對(duì)于scale而言

visual viewport寬度 = ideal viewport寬度  / 當(dāng)前縮放值
當(dāng)前縮放值 = ideal viewport寬度(設(shè)備的寬度)  / visual viewport寬度(可視區(qū)域的寬度)

現(xiàn)在再來(lái)說(shuō)下initial-scale的默認(rèn)值問(wèn)題,就是不寫(xiě)這個(gè)屬性的時(shí)候,它的默認(rèn)值會(huì)是多少呢?很顯然不會(huì)是1,因?yàn)楫?dāng) initial-scale = 1 時(shí),當(dāng)前的layout viewport寬度會(huì)被設(shè)為 ideal viewport的寬度,但前面說(shuō)了,各瀏覽器默認(rèn)的 layout viewport寬度一般都是980啊,1024啊,800啊等等這些個(gè)值,沒(méi)有一開(kāi)始就是 ideal viewport的寬度的,所以 initial-scale的默認(rèn)值肯定不是1。

根據(jù)測(cè)試,我們可以在iphone和ipad上得到一個(gè)結(jié)論,就是無(wú)論你給layout viewpor設(shè)置的寬度是多少,而又沒(méi)有指定初始的縮放值的話,那么iphone和ipad會(huì)自動(dòng)計(jì)算initial-scale這個(gè)值,以保證當(dāng)前layout viewport的寬度在縮放后就是瀏覽器可視區(qū)域的寬度

如果不設(shè)置meta viewport標(biāo)簽,那么移動(dòng)設(shè)備上瀏覽器默認(rèn)的寬度值為800px,980px,1024px等這些,總之是大于屏幕寬度的,所以會(huì)出現(xiàn)滾動(dòng)條。這里的寬度所用的單位px都是指css中的px,它跟代表實(shí)際屏幕物理像素的px不是一回事

回到我們的實(shí)踐中
此時(shí)我們可以在sass中寫(xiě)一個(gè)px2rem的方法,這樣就不用每次手算了

$first-yellow: 75
@function px2rem($px) {
  @return ($px / 15) * 1rem
}

視覺(jué)稿上有個(gè)div量出來(lái)是750px*300px,我們的樣式就可以這樣寫(xiě)

div{
    width: px2rem(750);
    height: px2rem(300)
}

這樣計(jì)算出來(lái)的單位就是rem了,就可以適配所有的設(shè)備了,該元素在視覺(jué)稿上面占有什么樣的比例,在所有設(shè)備上都會(huì)是一樣,可以利用數(shù)學(xué)公式推導(dǎo)一番,

現(xiàn)在有兩臺(tái)設(shè)備,我們的視覺(jué)稿是按照設(shè)備1設(shè)計(jì)的,我們可以看看在設(shè)備2上面元素的所占比例與設(shè)備1是否一樣

設(shè)備1相關(guān)參數(shù)
設(shè)備分辨率:dw1
邏輯分辨率:lw1

設(shè)備2相關(guān)參數(shù)
設(shè)備分辨率:dw2
邏輯分辨率:lw2

現(xiàn)在有某元素寬為x,在設(shè)備1上所占的比例應(yīng)為x/dw1(因?yàn)閁I是按照設(shè)備分辨率設(shè)計(jì)的)
對(duì)于設(shè)備1
dpr1 = dw1/lw1
按照rem = clientWidth * dpr / 10 得到 rem1 = lw1*dpr1/10 = lw1*(dw1/lw1)/10 = dw1/10
所以算出來(lái)width: x/rem1  + 'rem' 也就是width: 10*x/dw1 +'rem'

對(duì)于設(shè)備2
dpr2 = dw2/lw2
按照rem = clientWidth * dpr / 10 得到 rem2 = lw2*dpr2/10 = lw2*(dw2/lw2)/10 = dw2/10

可以得到在設(shè)備2上面元素顯示的width為 樣式里面寫(xiě)的值*設(shè)備2的rem,也就是
(10*x/dw1)*(dw2/10) = x*dw2/dw1
在設(shè)備2上面的所占的比例就是 顯示的寬度/設(shè)備2的寬度
所以rate = (x*dw2/dw1)/dw2 = x/dw1   也就是設(shè)備1上所占的比例,所以他們的展示樣式是一樣的

ps:記得有文字的地方一定要設(shè)置font-size,不然會(huì)繼承html根元素的,就會(huì)顯得很大,對(duì)于文字大小的適配不建議使用rem,可以使用媒體查詢(xún)

div{
    font-size: 40px;
    -webkit-transition:font-size 0.2s ease-out;
}

@media only screen and (max-width: 1200px) { div{ font-size: 39px; }}
@media only screen and (max-width: 1100px) { div{ font-size: 38px; }}
@media only screen and (max-width: 1000px) { div{ font-size: 37px; }}
@media only screen and (max-width: 900px) { div{ font-size: 36px; }}
@media only screen and (max-width: 800px) { div{ font-size: 35px; }}
@media only screen and (max-width: 700px) { div{ font-size: 34px; }}
@media only screen and (max-width: 600px) { div{ font-size: 33px; }}
@media only screen and (max-width: 500px) { div{ font-size: 32px; }}
@media only screen and (max-width: 400px) { div{ font-size: 31px; }}
@media only screen and (max-width: 300px) { div{ font-size: 30px; }}

寫(xiě)文章是為了更好的總結(jié),不總結(jié)就會(huì)忘記。

參考自:
從設(shè)備像素比到移動(dòng)適配
http://blog.csdn.net/u012402190/article/details/70172371

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容