px/em/rem的關係與區別

1px有多大?

我們先了解幾個概念:

關鍵概念
設備像素:設備屏幕實際擁有的像素點一般來說:寬度方向有1920個像素點,長度方向有1080個像素點。

邏輯像素:CSS 的像素單位(就是我們這次要討論的css的px),其尺寸大小是相對的,也稱爲獨立像素

分辨率:屏長的設備像素 × 屏寬的設備像素(1920 * 1080)

ppi(pixels per inch):像素密度,表示沿對角線每英寸長度的像素數目(單位是dpi),越大顯示的越細膩

縮放因子(Scale Factor):邏輯像素相對於設備像素的放大比例,可通過` window.devicePixelRatio `獲得,pc上可以用個個性化來設置,但二者並不完全等同
上面概念直接的關係
關係一:

  設備尺寸 × 像素密度 = 分辨率(設備像素)

舉例:

  iphone6s 對角線長度爲5.5 inches,像素密度401 ppi,分辨率 1920 * 1080,計算可得對角線的設備像素爲2205.5。

  5.5 * 401 = 2205.5

關係二:

  邏輯像素(css的px) = 設備像素 × 縮放因子

舉例:

  iphone6邏輯像素爲375 * 667,分辨率爲750 * 1334,縮放因子爲2

  1個邏輯像素(1px) = 設備寬度的1/375

  1個設備像素 = 設備寬度的1/750

  1/375 = 1/750 * 2

以上參考: 1px 究竟是多大

由公式得出的結論

PC端分辨率一樣的情況下,屏幕尺寸越大,顯示的越模糊(因爲dpi越小)。

舉例說明:

我們的臺式機電腦屏幕一般是32英寸,分辨率爲:1920 * 1080。而一般筆記本是15.6英寸,分辨率也是:1920*1080的。由公式一:當分辨率一樣時,設備尺寸越大,像素密度越小。所以32寸的臺式電腦看上去模糊一些。

相同分辨率,相同縮放因子情況下,不同設備尺寸下,表現是一致的
舉例說明:

平時我們在pc上24英寸的電腦上開發的網頁直接寫的(px),在不做任何兼容處理的情況下,在15.6英寸的筆記本上也能正常顯示。由公式二:因爲一般pc端,默認情況下縮放因子爲1(window.devicePixelRatio = 1),分辨率也一樣(1920 * 1080),那麼得到的**邏輯像素(css的px)**也是一樣的。所以你在分辨率一樣的情況下,在大屏電腦上設置的100px,在小屏電腦上也是100px。只是他們表現出來的大小不一致,小屏上面的1px更小。

如何將pc網頁放到手機上展示?

我們可以調整網頁在移動端上的縮放比例,這個值就是viewport。默認情況下,移動端瀏覽器會將 viewport 寬度設爲980px(也有可能是1024px 或其它值),也就是說1px = 設備屏幕寬度的1/980。這跟縮放因子沒有任何關係。
這時的1px 非常小,所有的元素都變得非常小,移動端瀏覽器之所以這麼做,是爲了儘可能完整的顯示 PC 端的網頁,然後允許用戶通過縮放來查看細節。
顯然體驗就別的特別差了,很多本來就比較小的元素看都看不清了。
第二種方式是我們設置一個適當的縮放比例。一般我們這樣設置:

<meta name="viewport" content="width=device-width">

那麼對於iphone6來說根據公式:1px = 1/750(分辨率) * 2(縮放因子) = 1/ 375。顯然比剛纔的1/980大了不少,那麼我們的元素如果還是按照原來的px去設置,那麼屏幕肯定展示不下去了,這時候,如果我們的元素的px值能根據1px的大小是動態調整,我們的網頁就完美了,這時候em,rem就派上用場了。

em是什麼?

上面提到,想讓我們的網頁在不同分辨率的設備(移動端)上正常顯示,最好我們的元素長寬,外邊距,內邊距等都是動態的

方式一:

上面說到,我們在移動端一般這樣設置:

<meta name="viewport" content="width=device-width;initial-scale=1" >

這個時候我們1px的大小就已知,iPhone6上爲:1px = 1/750(分辨率) * 2(縮放因子) = 1/ 375。既然1px的大小固定了,那麼我們只能動態改變一個元素設置的px了,比如說在iPhone8上是120px;而在iPhone6上需要是100px。這時候我們可以用js去動態計算,根據屏幕大小。但是顯然很麻煩,需要對每一個元素的長寬,內邊距,外邊距都需要調整,這顯然是一個巨大的工程。
這時候我們就可以用到em這個單位了,em單位的名稱爲相對長度單位,是根據它父元素的字體大小來計算的,一般默認情況下:16px = 1em。如果父元素font-size:16px,子元素margin:0.8em。那麼得到的大小就是:0.8 * 16 =12.8。當所有單位都採用em時,我們只需要改變bodyfont-size,那麼其他子元素寬度就能動態變化了,顯然方便很多。

rem是什麼?

'rem’是’css3’新增的一個相對長度單位,它的出現是爲了解決em的缺點,em可以說是相對於父級元素的字體大小,當父級元素字體大小改變時,又得重新計算。rem出現就可以解決這樣的問題,rem只相對於根目錄,即HTML元素。有了rem這個單位,我們只需要調整根元素htmlfont-size就能達到所有元素的動態適配了,附上一段常用適配代碼:

 /**
    * ================================================
    *   設置根元素font-size
    * 當設備寬度爲375(iPhone6)時,根元素font-size=16px; 
    × ================================================
    */
(function (doc, win) {
  var docEl = win.document.documentElement;
  var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
  
  var refreshRem = function () {
    var clientWidth = win.innerWidth
                      || doc.documentElement.clientWidth
                      || doc.body.clientWidth;

    console.log(clientWidth)
    if (!clientWidth) return;
    var fz;
    var width = clientWidth;
    fz = 16 * width / 375;
    docEl.style.fontSize = fz + 'px';//這樣每一份也是16px,即1rem=16px
  };

  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, refreshRem, false);
  doc.addEventListener('DOMContentLoaded', refreshRem, false);
  refreshRem();

})(document, window);

總結

  1. 邏輯像素(css的px) = 設備像素 × 縮放因子
  2. 爲了移動端更好的適配我們引入了emrem這2個動態單位
  3. em的大小與父元素的font-size有關,rem的大小與根元素htmlfont-size有關
  4. 一般在移動端我們會使用js動態計算跟節點htmlfont-size來達到自適應的目的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章