從理解開始 談談px rem 和 em 的區別與聯繫

概述

古語有云,沒有規矩則不成方圓。秦滅六國以後爲了促進國內生產力的發展,也是大力推動全國度量衡的統一。車同軌,書同文。與「尺寸」相關的問題(手動滑稽),從古至今一直爲人們所關注。因此在個人處女文章中,也決定大致講講在前端領域裏面的「尺寸」問題。css

目前的國內的前端開發圈子中,最常使用到的關於「尺寸」的單位,應該是 px , rem , em 這三位。本文主要介紹這三種尺寸單位是怎麼來的,能作什麼,要怎麼用。html


px(邏輯像素)

在通常的計算機應用中,px表示像素點,即屏幕上每個可發光的單元點,好比咱們所說的1080p屏幕,那指的就是寬度達到1080px的屏幕,還有2k屏,4k屏,也是經過計算像素點的數量而得出的屏幕分類與稱呼。從理論上來講,像素點是顯示終端最小的可顯示單位,小於1個像素的內容,是沒有辦法完美的顯示在屏幕上。這也是爲何早期屏幕的畫面容易出現鋸齒的緣由。前端

上面這一段所介紹的是硬件上的像素,通常咱們稱爲「物理像素」。而在前端的長度單位裏面的px的概念,與「物理像素」略有不一樣。瀏覽器在某些設備(如iphone系列)上,會將兩個甚至更多的物理像素點合併爲一個顯示上的「點」去進行計算和渲染。這就涉及到另外一個概念:「dpr」,這個在後面的文章會進一步深刻介紹。而在瀏覽器上的一個「點」,咱們稱爲「邏輯像素」,與「物理像素」概念相對應,也就是咱們在css上所使用的 px 。chrome

px單位的使用很是簡單,好比咱們須要一個寬度爲300px,高度爲100px的長方形div:瀏覽器

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>px單位長方形</title>
        <style>
            #test1{width:300px;height:100px;background:#bfa;}
        </style>
    </head>
    <body>
        <div id="test1"></div>
    </body>
</html>

使用px做爲單位,對於pc端的開發來講具備較大的優點:iphone

  1. PC端的項目設計圖的寬度和高度比例基本固定,並且屏幕相對較寬,使用px單位對於普通項目不會形成太多不友好的顯示效果。
  2. 對於設計師與前端開發者對接而言,使用px單位可以下降單位轉換的成本,提升開發速度。
  3. px概念比較清晰,對於入門開發者而言使用門檻低,比較友好。

但若是是在移動端的開發上,px做爲單位則顯得有些力不從心了。模塊化

因爲手機以及平板電腦等移動終端的普及,移動端的開發也已經佔了前端開發的半壁江山。而移動端因爲其設備終端分辨率尺寸的多樣化,以及橫豎屏切換致使寬高比差別較大等緣由。使用固定的px做爲尺寸單位就很容易出現字體、形狀的過大或太小,對於用戶瀏覽和使用網站來講形成困擾。而爲了解決這一問題,w3c標準也從最初的px單位開始,衍生出瞭如 em , rem , vh ,vh 等一系列單位。而在中國國內,使用最爲普遍的就是 rem 單位。但要說 rem 單位以前,咱們首先要來講一說 em 這個單位。字體

em(父元素字體大小)

em 與 rem 只差了一個字母,他們的概念也是相近。理解了 em 就能更好的理解 rem 這個單位。網站

相傳從3000多年前古埃及的紙草書中,發現了人前臂的圖形。用人的前臂做爲長度單位叫「腕尺」;10世紀英國國王埃德加,把他的拇指關節之間的長度定爲「1寸」。這裏的「腕尺」和「寸」,其實是一種相對的單位,若是兩個埃及法老,一個身高一米五不到,一個身高兩米,那他們的「腕尺」長度確定是不同的。但毫無疑問的是,他們的子民都會跟隨他們的法老使用一樣的「腕尺」做爲他們的長度量度單位。因此只要新法老一上任,全國子民的「腕尺」也會跟着改變。而em單位,在原理上與這一制度至關接近。ui

em 的定義是元素所屬的父元素的字體大小。若是某個元素的字體大小(font-size)爲20px,那麼它裏面的元素的 1em 換算過來也是20px。

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>em單位</title>
        <style>
            .content{  background: #bfa;  }
        </style>
    </head>
    <body>
        <div id="test1" style="font-size: 50px">
            <!-- test1的字體大小是50px,因此裏面的content  實際寬度是150px;實際高度是50px-->
            <div class="content" style="width: 3em;height: 1em;"></div>
        </div>
        <br/><br/>
        <div id="test2"  style="font-size: 20px">
            <!-- test2的字體大小是20px,因此裏面的content  實際寬度是60px;實際高度是20px-->
            <div class="content" style="width: 3em;height: 1em;"></div>
        </div>
    </body>
</html>

em的單位通常的使用場景爲段前段後的空行,或是在按字號倍數設置行高(如word中經常使用的1.5倍/2倍行高等),另外,對於模塊化的設計而言,採用em單位應該也是一個不錯的方案(模塊內的元素統一度量單位,編輯時只需修改模塊字體大小一個參數)。

rem(根節點字體大小)

理解了 em 單位以後,rem 這個就比較好理解了。rem 裏面的這個「r」表明的就是 root ,也就是根。rem所指的也是整個html文檔的根節點(html)的字體大小。若是說 em 是一方諸侯,那 rem 那就是號令四海八荒的天子了。只要元素是在html文檔中顯示,不管其是否脫離文檔流,是否有絕對定位、固定定位等影響,元素中的1rem都是html標籤上所定義的font-size。

也正是rem的這一種惟一性,使其在移動端的開發中備受青睞。還在使用px的日子裏,每適配一個屏幕,各個元素的尺寸大小所有要算一遍,心好累。自從使用了rem,屏幕大小有變化,那隻要根節點(html)的字體大小一變,就如同皇上下的聖旨,八荒六合無不拜服,各個元素麻溜地就把本身的尺寸給跟着調整過來了,順心!

在這裏我分享一套rem適配方案,並補充一些自個人註釋:

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!-- viewport設置視口參數,寬度爲設備寬度,縮放比例固定爲1-->
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0, minimal-ui">
        <title>rem解決方案</title>
        <script>
            (function(win) {
                var doc = win.document;
                var html = doc.documentElement;
    //            基於640px方案的設計稿
    ////////////////////////////////////////////////////
    //            通用的作法是將設計稿中的100px換算爲1rem
    //            所以,當咱們已知設計稿的寬度baseWidth,還有屏幕的實際寬度clientWidth時,1rem對於屏幕的實際寬度爲:
    //            html-font-size =  clientWidth / (baseWidth/100) px
    ///////////////////////////////////////////////////
                        var baseWidth = 640,
                        grids = baseWidth / 100,
                        resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize',
                        recalc = function() {
    //                        默認尺寸爲320px
                            var clientWidth = html.clientWidth || 320;
    //                        若是屏幕尺寸大於640,則按640寬度進行計算
                            if (clientWidth > 640) {
                                clientWidth = 640
                            }
    
                            html.style.fontSize = clientWidth / grids + 'px';
                            document.querySelector('.content').style.display = 'block';
                        };
                if (!doc.addEventListener) return;
                win.addEventListener(resizeEvt, recalc, false);
                doc.addEventListener('DOMContentLoaded', function() {
                    setTimeout(recalc)
                }, false);
            })(window);
        </script>
        <style>
            @media screen and (min-width: 641px) {
                /*當屏幕大小大於640px時,顯示區域寬度爲640px並水平居中*/
                .content {
                    width: 640px;
                    margin: auto;
                }
            }
            .content{background: #baf;}
            .rem_box{
                width: 3.2rem;
                background: #fba;
                font-size: 0.2rem;
                margin: auto;
            }
        </style>
    </head>
    <body>
        <div class="content">
            <div class="rem_box">
                不管屏幕如何縮放,橙色區域的寬度永遠是紫色區域寬度的一半,裏面的字體大小也會隨屏幕大小變化而同步變化(除非小於12px)
            </div>
        </div>
    </body>
</html>

rem的使用比較普遍並且成熟,包括像手機淘寶等網站項目,也是使用了rem做爲其解決方案。目前現代瀏覽器對於rem的支持也是至關不錯,下面是canIuse上提供的rem的兼容性查詢結果。

rem_canIuse.jpg


本文到這裏也就接近尾聲了,px rem 和 em 這三個概念在前端的知識中理解起來不算困難,一樣也不須要死記硬背。只要肯多寫,多試,多練,相信不用多久,你也能熟練掌握這三種利器,而且運用到實際的開發過程當中。

相關文章
相關標籤/搜索