精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
了解真實(shí)的『REM』手機(jī)屏幕適配


作者:hbxeagle

鏈接:github.com/hbxeagle/rem/blob/master/README.md


rem 作為一個(gè)低調(diào)的長(zhǎng)度單位,由于手機(jī)端網(wǎng)頁的興起,在屏幕適配中得到重用。使用 rem 前端開發(fā)者可以很方便的在各種屏幕尺寸下,通過等比縮放的方式達(dá)到設(shè)計(jì)圖要求的效果。


rem 的官方定義『The font size of the root element.』,即以根節(jié)點(diǎn)的字體大小作為基準(zhǔn)值進(jìn)行長(zhǎng)度計(jì)算。一般認(rèn)為網(wǎng)頁中的根節(jié)點(diǎn)是 html 元素,所以采用的方式也是通過設(shè)置 html 元素的 font-size 來做屏幕適配,但實(shí)際情況真有這么簡(jiǎn)單嗎?


首先我們來看看使用 rem 實(shí)現(xiàn)手機(jī)屏幕適配的常用方案。


以設(shè)計(jì)稿的寬度為640px,即:designWidth = 640,同時(shí)設(shè)定在640px屏寬下 1rem=100px ,即:rem2px = 100。


設(shè)置 1rem=100px 的優(yōu)點(diǎn)不言而喻。前端開發(fā)者在切圖、重構(gòu)頁面的時(shí)候,通過直接位移小數(shù)點(diǎn)的方式,就可以將UI圖中測(cè)量到的 px 值換算成對(duì)應(yīng)的 rem 值,方便快捷。


此外,在 head 中我們還設(shè)置了:<meta name='viewport' content='width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0' />

viewport 的作用很重要,但不是本文的重點(diǎn)所以不展開,有興趣的同學(xué)可以自行搜索。


先來看看具體方案:


下面四個(gè)方案來自同事共享,原理都是采用等比縮放的方式 —— 獲得目標(biāo)屏幕寬度和設(shè)計(jì)稿寬度的比,作為 rem 的基值(縮放系數(shù)),設(shè)置為html標(biāo)簽的字體大小。不同的只是在于性能取舍和書寫習(xí)慣。


方案1


@media screen and (min-width: 320px) {html{font-size:50px;}}

@media screen and (min-width: 360px) {html{font-size:56.25px;}}

@media screen and (min-width: 375px) {html{font-size:58.59375px;}}

@media screen and (min-width: 400px) {html{font-size:62.5px;}}

@media screen and (min-width: 414px) {html{font-size:64.6875px;}}

@media screen and (min-width: 440px) {html{font-size:68.75px;}}

@media screen and (min-width: 480px) {html{font-size:75px;}}

@media screen and (min-width: 520px) {html{font-size:81.25px;}}

@media screen and (min-width: 560px) {html{font-size:87.5px;}}

@media screen and (min-width: 600px) {html{font-size:93.75px;}}

@media screen and (min-width: 640px) {html{font-size:100px;}}

@media screen and (min-width: 680px) {html{font-size:106.25px;}}

@media screen and (min-width: 720px) {html{font-size:112.5px;}}

@media screen and (min-width: 760px) {html{font-size:118.75px;}}

@media screen and (min-width: 800px) {html{font-size:125px;}}

@media screen and (min-width: 960px) {html{font-size:150px;}}


方案2


@media screen and (min-width: 320px) {html{font-size:312.5%;}}

@media screen and (min-width: 360px) {html{font-size:351.5625%;}}

@media screen and (min-width: 375px) {html{font-size:366.211%;}}

@media screen and (min-width: 400px) {html{font-size:390.625%;}}

@media screen and (min-width: 414px) {html{font-size:404.2969%;}}

@media screen and (min-width: 440px) {html{font-size:429.6875%;}}

@media screen and (min-width: 480px) {html{font-size:468.75%;}}

@media screen and (min-width: 520px) {html{font-size:507.8125%;}}

@media screen and (min-width: 560px) {html{font-size:546.875%;}}

@media screen and (min-width: 600px) {html{font-size:585.9375%;}}

@media screen and (min-width: 640px) {html{font-size:625%;}}

@media screen and (min-width: 680px) {html{font-size:664.0625%;}}

@media screen and (min-width: 720px) {html{font-size:703.125%;}}

@media screen and (min-width: 760px) {html{font-size:742.1875%;}}

@media screen and (min-width: 800px) {html{font-size:781.25%;}}

@media screen and (min-width: 960px) {html{font-size:937.5%;}}


方案3


var designWidth = 640, rem2px = 100;

document.documentElement.style.fontSize =

  ((window.innerWidth / designWidth) * rem2px) 'px';


方案4


var designWidth = 640, rem2px = 100;

document.documentElement.style.fontSize =

  ((((window.innerWidth / designWidth) * rem2px) / 16) * 100) '%';


為了更避免理解上的混亂,我在上面js的代碼中加了 ( ) ,實(shí)際代碼中是不需要的。

詳細(xì)分析一下,rem 和 px 直接的轉(zhuǎn)換公式可以寫為:


1rem = 1 * htmlFontSize


htmlFontSize 為 html 元素的字體大小。


首先來看方案1中,在屏寬為640px情況下的設(shè)置:


@media screen and (min-width: 640px) {html{font-size:100px;}}


可以很明顯的表現(xiàn)出這一點(diǎn) 1rem = 1 * 100px ,同我們最初的設(shè)定。那么我們要得到其它屏幕大小的 htmlFontSize 值要怎么辦。很簡(jiǎn)單如方案3,因?yàn)槲覀兊牟捎玫缺瓤s放的方式適配,所以計(jì)算目標(biāo)屏幕寬度和設(shè)計(jì)稿的寬度的比即可:


window.innerWidth / designWidth * rem2px 'px'


由于瀏覽器默認(rèn)字體大小為 16px,所以當(dāng)我們使用百分比作為根節(jié)點(diǎn) html 的字體大小時(shí),即html元素的font-size值設(shè)置為一個(gè)百分比值,rem 的計(jì)算方式就會(huì)改為:


defaultFontSize = 16px

1rem = 1 * htmlFontSize * defaultFontSize


如方案2中,在屏寬為640px情況下的設(shè)置:


@media screen and (min-width: 640px) {html{font-size:625%;}}


應(yīng)用上面的公式:


1rem = 1 * 625% * 16px

其中:625% * 16 = 6.25 * 16 = 100

所以:1rem = 1 * 100px


同樣的可以得到所有屏幕大小下,html 的 font-size 值的計(jì)算公式,即為方案4:


window.innerWidth / designWidth * rem2px / 16 * 100   '%'


通過方案3和方案4的公式,就可以很方便的生成方案1和方案2中的css。


這里只給出了方案3和方案4對(duì)應(yīng)驗(yàn)證頁面(方案1和方案2是它們的變形): scheme3.html(http://htmlpreview.github.io/?https://github.com/hbxeagle/rem/blob/master/scheme3.html), scheme4.html(http://htmlpreview.github.io/?https://github.com/hbxeagle/rem/blob/master/scheme4.html)


如下面兩張圖,是在屏寬為360px下的效果,通過計(jì)算目標(biāo)為:1rem = 56.25px。方案3設(shè)置值為:56.25px,方案4設(shè)置值為:351.5625%



到目前為止貌似很完美的解決了問題,實(shí)際情況當(dāng)然是出現(xiàn)了意外。在有些 Android 手機(jī)上,瀏覽器或 webview 的默認(rèn)字體是隨著系統(tǒng)設(shè)置的字體改變的。這樣就會(huì)導(dǎo)致默認(rèn)字體大于或小于 16px。

修改默認(rèn)字體大小后,我們?cè)倏捶桨?和方案4。


同樣在屏寬為360px下,我們調(diào)大系統(tǒng)字體大小,如下面的效果


設(shè)置前 html 元素的字體大小的計(jì)算值為 18px ,設(shè)置后的計(jì)算值為 65px ,由于屏幕寬度沒有改變,我們的目標(biāo)值,即我們?cè)?html 元素上設(shè)置的 font-size 值也沒有變化任然為 56.25px,而最終計(jì)算值出現(xiàn)了偏差。




分析偏差前,先來看在360px屏寬下,方案3和方案4的計(jì)算過程:


方案3:


document.documentElement.style.fontSize = 56.25px

htmlFontSize = 56.25px

1rem = 1 * htmlFontSize = 56.25px

實(shí)際為:

1rem = 64.6875px


方案4:


document.documentElement.style.fontSize = 351.5625%

htmlFontSize = 351.5625%

defaultFontSize = 18px

1rem = 1 * htmlFontSize * defaultFontSize = 351.5625% * 18px = 63.28125px

351.5625% * 18 = 63.28125

實(shí)際為:

1rem = 64.6875px


貌似方案4的計(jì)算結(jié)果很接近實(shí)際效果,而方案3偏差很大。再來比較方案3和方案4的計(jì)算公式:


// 方案3

document.documentElement.style.fontSize =

  window.innerWidth / designWidth * rem2px 'px';

 

// 方案4

document.documentElement.style.fontSize =

  window.innerWidth / designWidth * rem2px / 16 * 100 '%';


方案4較于方案3其實(shí)多除了一個(gè)16,可以推測(cè)瀏覽器在計(jì)算 rem 的具體值時(shí),如果 html 設(shè)置的 font-size 為 px 值時(shí)會(huì)先除以 16 ,然后再乘以 htmlFontSize。


1rem = 1 * (56.25px / 16) * 18

1 * (56.25 / 16) * 18 = 63.28125


方案4存在問題,是因?yàn)橄到y(tǒng)的默認(rèn)字體改為了 18px ,但是我們?cè)谟?jì)算百分比是時(shí)候,還是以 16px 為基準(zhǔn)值進(jìn)行計(jì)算,所以出現(xiàn)偏差(計(jì)算值和實(shí)際值之間還有一點(diǎn)偏差這個(gè)在后面會(huì)提到)。


而在方案3中,我們其實(shí)是不考慮瀏覽器默認(rèn)字體大小的,但在實(shí)際使用的過程中,瀏覽器還是除了 16 ,而此時(shí)默認(rèn)字體大小為 18px。得出如下在 html 的 fontSize 設(shè)置為 px 的情況下 rem 的計(jì)算公式為:


1rem = 1 * (htmlFontSize / 16) * defaultFontSize


在系統(tǒng)設(shè)置的字體大小發(fā)生改變時(shí),defaultFontSize 會(huì)跟著改變,而 16 不會(huì)變化。所以方案3雖然表面上不考慮默認(rèn)字體大小的變化,只關(guān)注屏幕與設(shè)計(jì)稿之間的寬度比,但在實(shí)際計(jì)算中還是使用到了默認(rèn)字體大小,而且還有一個(gè)不變的 16 在作祟,導(dǎo)致方案3失敗。


所謂的「root element」其實(shí)不是想象的那樣,一個(gè)是16,一個(gè)是18,到底取的是那個(gè) root element 的字體大小。


ok,rem 的計(jì)算的時(shí)候,px 的方式會(huì)有一個(gè)16不隨系統(tǒng)字體大小改變,所以我們采用百分比的方案,繞開這個(gè)問題。


采用百分比的方案4因?yàn)樵谟?jì)算時(shí)寫死了默認(rèn)字體大小 16px。所以它的偏差在于沒能動(dòng)態(tài)的獲取默認(rèn)字體大小。更新如下:


方案4.1


var designWidth = 640, rem2px = 100;

var h = document.getElementsByTagName('html')[0];

var htmlFontSize = parseFloat(window.getComputedStyle(h, null)

                                    .getPropertyValue('font-size'));

 

document.documentElement.style.fontSize =

  window.innerWidth / designWidth * rem2px / htmlFontSize * 100 '%';


效果如下圖:


16px 的圖中,設(shè)置后的 html 的 font-size 與 1rem 的實(shí)際值有偏差,同時(shí) 6.4rem 的計(jì)算值也有偏差。通過查看代碼發(fā)現(xiàn)html的font-size使用的是: getPropertyValue('font-size') 而 1rem 使用的是getPropertyValue('width'),偏差出在計(jì)算 font-size 的時(shí)候?yàn)g覽器進(jìn)行了四舍五入。rem 定義中的另一個(gè)元素「font size」也不能按字面意思使用,宣告失守。


18px 中的偏差,以及上文中方案4在 18px 實(shí)際值和計(jì)算值出現(xiàn)的偏差都是同樣的問題。所以基準(zhǔn)值還需要修改。




在更新一版,方案4.2:


var designWidth = 640, rem2px = 100;

var d = window.document.createElement('div');

d.style.width = '1rem';

d.style.display = 'none';

var head = window.document.getElementsByTagName('head')[0];

head.appendChild(d);

var defaultFontSize = parseFloat(window.getComputedStyle(d, null).getPropertyValue('width'));

d.remove();

document.documentElement.style.fontSize =

  window.innerWidth / designWidth * rem2px / defaultFontSize * 100 '%';


效果如下圖:




到此為止,rem 在默認(rèn)字體不是 16px 的情況下的處理已經(jīng)解決,考慮到還有設(shè)計(jì)屏幕旋轉(zhuǎn),最終手機(jī)端的解決方案為:


function adapt(designWidth, rem2px){

  var d = window.document.createElement('div');

  d.style.width = '1rem';

  d.style.display = 'none';

  var head = window.document.getElementsByTagName('head')[0];

  head.appendChild(d);

  var defaultFontSize = parseFloat(window.getComputedStyle(d, null).getPropertyValue('width'));

  d.remove();

  document.documentElement.style.fontSize = window.innerWidth / designWidth * rem2px / defaultFontSize * 100 '%';

  var st = document.createElement('style');

  var portrait = '@media screen and (min-width: ' window.innerWidth 'px) {html{font-size:' ((window.innerWidth/(designWidth/rem2px)/defaultFontSize)*100) '%;}}';

  var landscape = '@media screen and (min-width: ' window.innerHeight 'px) {html{font-size:' ((window.innerHeight/(designWidth/rem2px)/defaultFontSize)*100) '%;}}'

  st.innerHTML = portrait landscape;

  head.appendChild(st);

  return defaultFontSize

};

var defaultFontSize = adapt(640, 100);


回過頭來再看 rem 的定義,『The font size of the root element.』。我們以為的 root element —— html 其實(shí)還有個(gè)影子在作祟,而我們以為的 font-size 其實(shí)是個(gè)近似值。



關(guān)注「前端大全」

看更多精選前端技術(shù)文章

↓↓↓

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
demo.html
相對(duì)單位rem以及文本溢出處理方法
Sass基礎(chǔ)——Rem與Px的轉(zhuǎn)換
css中單位em和rem的區(qū)別
web app變革之rem
淺談移動(dòng)端適配大法
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 陈巴尔虎旗| 措美县| 获嘉县| 永修县| 同江市| 通辽市| 邯郸市| 江西省| 通榆县| 绥江县| 西林县| 馆陶县| 丰镇市| 许昌县| 江山市| 化德县| 安龙县| 南陵县| 大渡口区| 夏津县| 罗平县| 望江县| 从江县| 横山县| 黄骅市| 古丈县| 营山县| 垫江县| 屯昌县| 云林县| 遂溪县| 鹿泉市| 朝阳县| 澄城县| 石渠县| 泽库县| 富民县| 永登县| 中宁县| 榕江县| 浦县|