px、em和rem實戰經驗

RRRookieG發表於2018-07-11

前言

在自適應佈局或者移動端網頁開發時,我們經常會用到em和rem兩個長度單位。接下來我們討論一下這兩個單位和px之間的區別,以及他們的使用場景等。

區別

px

px,畫素(計算機螢幕上的一個點)。(引自w3school-css單位

畫素(Pixels),相對長度單位,它是相對於顯示器螢幕解析度而言的,它相容性好而且精確,但是這種方法當使用者在縮放瀏覽器或者需要相容不同移動裝置時,我們的頁面佈局可能會被打破。

em

em為了解決上述問題而進化產生,也是相對長度單位,根據使用它的元素的大小決定(有人誤以為是根據父元素,那是因為使用它的元素繼承了父類的屬性,根據W3C標準可知 ,它們是基於當前物件元素的字型大小),它可以自動適應使用者所使用的字型。

em,相對長度單位。相對於當前物件內文字的字型尺寸。
如當前對行內文字的字型尺寸未被人為設定,則相對於瀏覽器的預設字型尺寸。(引自em-CSS3參考手冊

關於em值的計算

假設任意瀏覽器的預設字型大小都是16px。所有未經調整的瀏覽器中都是1em=16px。為了方便換算,我們通常在css中設定body的屬性 font-size:62.5%,這就使1em值變為10px,這樣我們就可以把設計稿的px值除以10,然後換上em作為單位來進行px和em的換算,十分簡單,例如16px可以改寫為1.6em。

rem

由於em值不是固定的,1em在不同元素下的值會因為該元素或者該元素父元素的大小不同而不同,因此在我們多次使用時,就會帶來開發的難度。這時候rem(root em)應運而生了。rem是相對於根(html)元素,這就意味著,我們只需要根據自己的需要給根元素確定一個參考值,然後通過它既可以做到只修改根元素就成比例地調整所有字型大小,又可以避免字型大小逐層複合的連鎖反應。最大的優點是提供一致尺寸,便於計算。

rem,相對長度單位。相對於根元素(即html元素)font-size計算值的倍數。(引自rem-CSS3參考手冊

根元素重寫

em 和 rem 單位之間的區別是瀏覽器根據誰來轉化成px值,em是基於當前物件內文字的字型尺寸決定,rem是基於html元素的字型大小來決定,而根(html)元素的字型大小如果沒有顯式地設定固定值去覆蓋,那麼它首先來自瀏覽器設定,因此瀏覽器的字型大小設定可以影響每個使用rem單元以及每個通過em單位繼承的值。為了還原設計稿和實現合理的佈局所以需要根元素重寫。瀏覽器縮放動態修改根元素大小可以參考以下程式碼段。

<script>
    var timer, style = document.head.appendChild(document.createElement("style"));
    var useREM = window.useREM = Object.create({
      resize: function () {
        var config=this.config;
        this.size=Math.max(config.min, Math.min(config.max, document.documentElement.clientWidth)) / config.num;
        style.innerHTML="html{font-size: "+ this.size +"px !important;}"
        return this;
      },
      set: function (newConfig) {
        if(newConfig){
          for (var a in newConfig){
            if(this.config.hasOwnProperty(a)){
              this.config[a]=newConfig[a];
            }
          }
        }
        this.resize();
        return this;
      }
    }, {
      size: {
        value: 20,
        writable: true,
        configurable: false,
        enumerable: true
      },
      config: {
        value:{
          max: 1200,//設定最大可視區寬
          min: 900,//設定最小可視區寬
          num: 10,//根據需求調整比例
          delay: 100
        },
        writable: false,
        configurable: false,
        enumerable: true
      }
    });

    addEventListener("resize", function () {
      clearTimeout(timer);
      timer = setTimeout(this.resize.bind(this), this.config.delay);
    }.bind(useREM));

    useREM.set();
    </script>

同時,也有人認為這種做法在一定程度上剝奪了使用者對瀏覽器字型設定的權利,他們的觀點是rem的好處是給了我們的一個途經去獲取使用者的偏好來影響網站中每一處使用rem的元素大小,無論使用者如何設定自己的瀏覽器,我們的佈局都能調整到合適大小。這個就暫不做討論吧,日後有機會再講。

使用場景

  • 如果這個屬性根據它的font-size進行測量,則使用em,其他的使用rem
  • 媒體查詢中使用 rem 單位
  • 不要在多列布局中使用 em 或 rem -改用 %

關於em和rem在完成模組化元件中的應用例項,你可以參考這篇文章

相容

  • 所有瀏覽器都支援px,除了IE8及以下版本,其它的瀏覽器都支援em和rem屬性。對於不支援它的瀏覽器,就多寫一個絕對單位的宣告。
  • IE9/IE10在用於偽元素時或者使用字型簡寫宣告時不支援rem
  • IOS Safari5.0-5.1雖然支援rem,但是在使用媒體查詢時不支援rem

工具

在這裡為大家提供一個px,em,rem單位轉換工具。地址:http://pxtoem.com/

討論區

  • csdn移動端和pc端兩套程式碼,兩種字號大小宣告,pc端用了px,沒有根據瀏覽器縮放自適應,移動端用了rem,根據螢幕寬度重寫了根元素,實現了自適應。
  • 掘金主頁用了rem,在mac的chrome中根元素固定12px,但是文字大小有根據瀏覽器縮放實現自適應。
  • 你們團隊是怎麼做的?

相關文章