自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

了解真實的『REM』手機屏幕適配

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

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

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

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

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

設(shè)置 1rem=100px 的優(yōu)點不言而喻。前端開發(fā)者在切圖、重構(gòu)頁面的時候,通過直接位移小數(shù)點的方式,就可以將UI圖中測量到的 px 值換算成對應(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 的作用很重要,但不是本文的重點所以不展開,有興趣的同學(xué)可以自行搜索。

先來看看具體方案:

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

方案1

  1. @media screen and (min-width: 320px) {html{font-size:50px;}} 
  2. @media screen and (min-width: 360px) {html{font-size:56.25px;}} 
  3. @media screen and (min-width: 375px) {html{font-size:58.59375px;}} 
  4. @media screen and (min-width: 400px) {html{font-size:62.5px;}} 
  5. @media screen and (min-width: 414px) {html{font-size:64.6875px;}} 
  6. @media screen and (min-width: 440px) {html{font-size:68.75px;}} 
  7. @media screen and (min-width: 480px) {html{font-size:75px;}} 
  8. @media screen and (min-width: 520px) {html{font-size:81.25px;}} 
  9. @media screen and (min-width: 560px) {html{font-size:87.5px;}} 
  10. @media screen and (min-width: 600px) {html{font-size:93.75px;}} 
  11. @media screen and (min-width: 640px) {html{font-size:100px;}} 
  12. @media screen and (min-width: 680px) {html{font-size:106.25px;}} 
  13. @media screen and (min-width: 720px) {html{font-size:112.5px;}} 
  14. @media screen and (min-width: 760px) {html{font-size:118.75px;}} 
  15. @media screen and (min-width: 800px) {html{font-size:125px;}} 
  16. @media screen and (min-width: 960px) {html{font-size:150px;}}  

方案2

  1. @media screen and (min-width: 320px) {html{font-size:312.5%;}} 
  2. @media screen and (min-width: 360px) {html{font-size:351.5625%;}} 
  3. @media screen and (min-width: 375px) {html{font-size:366.211%;}} 
  4. @media screen and (min-width: 400px) {html{font-size:390.625%;}} 
  5. @media screen and (min-width: 414px) {html{font-size:404.2969%;}} 
  6. @media screen and (min-width: 440px) {html{font-size:429.6875%;}} 
  7. @media screen and (min-width: 480px) {html{font-size:468.75%;}} 
  8. @media screen and (min-width: 520px) {html{font-size:507.8125%;}} 
  9. @media screen and (min-width: 560px) {html{font-size:546.875%;}} 
  10. @media screen and (min-width: 600px) {html{font-size:585.9375%;}} 
  11. @media screen and (min-width: 640px) {html{font-size:625%;}} 
  12. @media screen and (min-width: 680px) {html{font-size:664.0625%;}} 
  13. @media screen and (min-width: 720px) {html{font-size:703.125%;}} 
  14. @media screen and (min-width: 760px) {html{font-size:742.1875%;}} 
  15. @media screen and (min-width: 800px) {html{font-size:781.25%;}} 
  16. @media screen and (min-width: 960px) {html{font-size:937.5%;}}  

方案3

  1. var designWidth = 640, rem2px = 100; 
  2. document.documentElement.style.fontSize =  
  3.   ((window.innerWidth / designWidth) * rem2px) + 'px' 

方案4

  1. var designWidth = 640, rem2px = 100; 
  2. document.documentElement.style.fontSize =  
  3.   ((((window.innerWidth / designWidth) * rem2px) / 16) * 100) + '%' 

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

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

  1. 1rem = 1 * htmlFontSize 

htmlFontSize 為 html 元素的字體大小。

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

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

可以很明顯的表現(xiàn)出這一點 1rem = 1 * 100px ,同我們最初的設(shè)定。那么我們要得到其它屏幕大小的 htmlFontSize 值要怎么辦。很簡單如方案3,因為我們的采用等比縮放的方式適配,所以計算目標(biāo)屏幕寬度和設(shè)計稿的寬度的比即可:

  1. window.innerWidth / designWidth * rem2px + 'px' 

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

  1. defaultFontSize = 16px 
  2. 1rem = 1 * htmlFontSize * defaultFontSize  

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

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

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

  1. 1rem = 1 * 625% * 16px  

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

所以:1rem = 1 * 100px 

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

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

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

這里只給出了方案3和方案4對應(yīng)驗證頁面(方案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下的效果,通過計算目標(biāo)為:1rem = 56.25px。方案3設(shè)置值為:56.25px,方案4設(shè)置值為:351.5625%  

 

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

修改默認(rèn)字體大小后,我們再看方案3和方案4。

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

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

 

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

方案3:

  1. document.documentElement.style.fontSize = 56.25px 
  2. htmlFontSize = 56.25px 
  3. 1rem = 1 * htmlFontSize = 56.25px  

實際為: 

1rem = 64.6875px 

方案4: 

  1. document.documentElement.style.fontSize = 351.5625% 
  2. htmlFontSize = 351.5625% 
  3. defaultFontSize = 18px 
  4. 1rem = 1 * htmlFontSize * defaultFontSize = 351.5625% * 18px = 63.28125px 
  5. 351.5625% * 18 = 63.28125 

實際為: 

1rem = 64.6875px 

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

  1. // 方案3 
  2. document.documentElement.style.fontSize =  
  3.   window.innerWidth / designWidth * rem2px + 'px'
  4.   
  5. // 方案4 
  6. document.documentElement.style.fontSize =  
  7.   window.innerWidth / designWidth * rem2px / 16 * 100 + '%' 

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

  1. 1rem = 1 * (56.25px / 16) * 18 
  2. 1 * (56.25 / 16) * 18 = 63.28125  

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

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

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

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

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

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

采用百分比的方案4因為在計算時寫死了默認(rèn)字體大小 16px。所以它的偏差在于沒能動態(tài)的獲取默認(rèn)字體大小。更新如下:

方案4.1

  1. var designWidth = 640, rem2px = 100; 
  2. var h = document.getElementsByTagName('html')[0]; 
  3. var htmlFontSize = parseFloat(window.getComputedStyle(h, null
  4.                                     .getPropertyValue('font-size')); 
  5.   
  6. document.documentElement.style.fontSize =  
  7.   window.innerWidth / designWidth * rem2px / htmlFontSize * 100 + '%' 

效果如下圖:

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

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

 

 

 

在更新一版,方案4.2:

  1. var designWidth = 640, rem2px = 100; 
  2. var d = window.document.createElement('div'); 
  3. d.style.width = '1rem'
  4. d.style.display = "none"
  5. var head = window.document.getElementsByTagName('head')[0]; 
  6. head.appendChild(d); 
  7. var defaultFontSize = parseFloat(window.getComputedStyle(d, null).getPropertyValue('width')); 
  8. d.remove(); 
  9. document.documentElement.style.fontSize =  
  10.   window.innerWidth / designWidth * rem2px / defaultFontSize * 100 + '%' 

效果如下圖: 

 

 

 

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

  1. function adapt(designWidth, rem2px){ 
  2.   var d = window.document.createElement('div'); 
  3.   d.style.width = '1rem'
  4.   d.style.display = "none"
  5.   var head = window.document.getElementsByTagName('head')[0]; 
  6.   head.appendChild(d); 
  7.   var defaultFontSize = parseFloat(window.getComputedStyle(d, null).getPropertyValue('width')); 
  8.   d.remove(); 
  9.   document.documentElement.style.fontSize = window.innerWidth / designWidth * rem2px / defaultFontSize * 100 + '%'
  10.   var st = document.createElement('style'); 
  11.   var portrait = "@media screen and (min-width: "+window.innerWidth+"px) {html{font-size:"+ ((window.innerWidth/(designWidth/rem2px)/defaultFontSize)*100) +"%;}}"
  12.   var landscape = "@media screen and (min-width: "+window.innerHeight+"px) {html{font-size:"+ ((window.innerHeight/(designWidth/rem2px)/defaultFontSize)*100) +"%;}}" 
  13.   st.innerHTML = portrait + landscape; 
  14.   head.appendChild(st); 
  15.   return defaultFontSize 
  16. }; 
  17. var defaultFontSize = adapt(640, 100);  

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

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2013-05-22 09:49:36

2016-11-10 09:55:29

CSS

2022-01-15 23:08:03

手機屏幕曲面屏

2017-11-10 13:02:44

iOSUI代碼

2021-12-26 00:10:40

前端頁面響應(yīng)式

2015-02-05 14:31:45

iPhone適配

2015-11-02 09:49:04

Android屏幕適配官方指導(dǎo)

2021-09-26 16:08:49

手機屏幕技術(shù)

2015-04-27 13:48:30

手機解鎖身份識別

2021-12-30 22:35:09

手機屏幕分辨率

2021-04-20 20:09:56

LinuxScrcpy桌面應(yīng)用

2010-11-09 10:10:15

移動開發(fā)屏幕適配UI設(shè)計

2014-09-04 14:51:00

小屏幕界面設(shè)計app

2020-08-28 09:39:21

手機屏幕屏幕刷新率高刷新率

2020-04-24 13:40:09

邊緣計算開發(fā)數(shù)據(jù)中心

2020-04-24 12:06:08

邊緣計算數(shù)據(jù)中心

2016-12-06 08:25:13

2017-08-11 19:02:21

Android全屏幕適配

2013-04-22 10:27:47

2014-09-18 09:59:41

安卓郵箱適配屏幕
點贊
收藏

51CTO技術(shù)棧公眾號