你真的理解rem嗎?面試官再問你就這樣回答

 

​有一道高頻的面試題經常會出現,請你講一下em和rem的區別。

1. em與rem的區別

這個題目其實很簡單,基本上都能說出來,他們的本質區別就是參照的對象不同。

  • em是相對父元素的字體大小,如果父元素的字體大小是14px,那麼它子元素的2em就是28px,不同父元素的子元素的2em的實際大小是可能不同的。

  • rem是相對於根元素,即html元素,如果html的字體大小是14px,那麼在任何地方的2rem都是28px。

2. 爲什麼要用rem?

可能大多數人就回答道這裏就完了,那麼有沒有思考過爲什麼會有rem的存在,難道僅僅只是爲了是全文都有一個統一的相對元素嗎。

當然不可能這麼簡單,rem的出現及使用多用於移動端開發中,我們知道,移動端的設備寬度是不定的,如果我們使用固定的大小,那麼在不同大小的設備上就會出現佈局錯亂、留白、殘缺等現象的出現。

舉個例子,假設我們拿到的設計圖寬度爲750px,實際的設備寬度也是750px,這種情況真是好,實際與設計圖大小一樣,我們只需要把每個元素的大小全部按照設計圖的大小開發就可以了。但是如果實際設備寬度只有375px呢,縮小了一般,這是如果我們還是按照原來的大小進行開發,在設備上必然是無法完全顯示的。這是我們就需要將開發的元素實際大小都要縮小爲設計圖的一半,但是縮小後的只能在375px的設備上正常顯示,如果換做其他設備,佈局又會改變。

3. 如何解決

這時就可以用rem來解決,我們假設在設計圖中1rem = 100px,假設有個元素在設計圖中的大小爲50px,我們就可以寫成 0.5rem,如果是80px,可以寫成0.8rem。現在我們把開發後的內容放到實際設備中,設備寬度正好爲750的話,那麼1rem還是等於100px,如果設備爲375px,我們只需要把1rem設置爲50px,即根元素的字體大小爲50px;如果設備大小爲400px,那麼1rem就應該爲 (400/750)*100 = 53.3px。

4.動態計算

因爲設備的大小我們是無法預知的,所以1rem的大小在不同設備上也就不同,如果我們在加載時知道了設備的寬度,我們就可以根據這個寬度來動態的計算出在該設備上1rem究竟應該是多少,然後設置到html元素上。假設設計圖寬度爲designWidth,實際設備寬度爲windowWidth,那麼可以計算出實際的1rem = (designWidth/windowWidth)*100。這裏的100爲我們在設計圖中設置的1rem的大小,也叫基準值。

5. 爲什麼選100px作爲基準值

上面講到我們設置的基準值爲100px,當然也是可以設置50、14等來作爲基準值,那我們爲什麼要選100作爲基準值呢?

主要還是 爲了方便計算,20px換算後爲0.2rem,16px換算後爲0.16rem。如果基準值爲14的話,20px = 20/14 = 1.43rem,很明顯在計算上要麻煩很多。既然這樣,有人問了,我如果選1px作爲基準值豈不是更方便,14px就爲14rem,20px就爲20px。有個問題不要忽略了,瀏覽器的最小字體大小爲12px,所以設根元素的字體大小爲1px是不可以的,只能大於12px,大於12的就100計算最爲方便。

我的網站:http://www.dzyong.top/ ,覺得還不錯的話就關注我吧,不錯過我的每一篇推送,微信搜索:【前端筱園】

6. 實際案例

來看一個我們都熟悉的應用《淘寶》,淘寶的首頁就是一個嵌入網頁,網址:https://main.m.taobao.com/。它就是使用的rem,打開控制檯找到根元素html,當我改變頁面寬度時,可以看到html元素的寬度也在改變。
 

當我嘗試改變窗口使根元素font-size大小爲100px時,看到此時窗口的大小爲375px,375px也真是設計師常用的一個尺寸,此時的font-size爲100,說明淘寶的基準值就是我們說的100,還可以知道當時設計圖的寬度爲375px。

7. 代碼實現動態改變根元素大小

計算代碼如下,當頁面大小改變後需要重新計算:

$(function(){
  function setRem(){
    var windowWidth = $(window).width();
    console.log(windowWidth);
    var rem = parseInt(windowWidth/750*100)+'px';
    $('html').css('font-size',rem);
    console.log(rem)
  }
  setRem();
  var timer;
  $(window).on('resize',function(){
    timer=setTimeout(function(){
      clearTimeout(timer);
      setRem();
    },50)
  })
})

我的網站:http://www.dzyong.top/ 

覺得還不錯的話就關注我吧,不錯過我的每一篇推送

微信搜索:【前端筱園】

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章