CSS3中,常見的長度單位

 

  • vw、vh、vmin、vmax
  • rem與em

 

1、vw、vh、vmin、vmax

vhvwvminvmax這四個單位都是基於視口的,含義如下:

 

(1)vw、vh

vw是相對視口(viewport)的寬度而定的,長度等於視口寬度的1/100

假如瀏覽器的寬度爲200px,那麼1vw就等於2px(200px/100)。

vh是相對視口(viewport)的高度而定的,長度等於視口高度的1/100

假如瀏覽器的高度爲500px,那麼1vh就等於5px(500px/100)。

 

(2)vmin、vmax

vminvmax是相對於視口的高度和寬度兩者之間的最小值最大值

如果瀏覽器的高爲300px、寬爲500px,那麼1vmin就是3px,1vmax就是5px;如果瀏覽器的高爲800px,寬爲1080px,那麼1vmin也是8px,1vmax也是10.8px。

兼容性:兼容性

 

2、rem

rem是相對於根元素(html)的字體大小(font-size)來計算的長度單位。

html{font-size: 62.5%}  /* 10 ÷ 16 × 100% = 62.5% */



body{font-size: 1.4rem;} /* 1.4 × 

如果你沒有設置html的字體大小,就會以瀏覽器默認字體大小,一般是16px。

 

注意:由於瀏覽器默認最小字體大小的限制,如果設置的根元素字體大小小於默認最小字體大小,那麼就會以默認最小字體大小設置根元素。比如:在chrome中,最小字體大小是12px,如果你設置的字體大小小於12px,還是會以12px設置:

html{font-size: 62.5%}  /* 16px * 62.5% = 10px */

body{font-size: 1.4rem;} /* 1.4rem * 12px = 16.8px */

本意設置body的字體大小爲14px,可是實際上卻是16.8px,就是因爲10px小於12px,所以採取了12px。

 

所以,我一般都是這樣設置:


html{font-size: 20px;}



body{font-size: 0.7rem;}  /* 0.7 * 20px = 14px */

 

說到rem,我們還會想到em,兩者都是相對單位,由瀏覽器轉換爲像素值,那兩者有什麼區別?使用哪個更好呢?

 

remem的區別:

  • rem是相對於根元素(html)的字體大小,而em是相對於其父元素的字體大小
  • em最多取到小數點的後三位


<style>

  html{ font-size: 20px; }

  body{ 

    font-size: 1.4rem;  /* 1rem = 28px */

    padding: 0.7rem;  /* 0.7rem = 14px */

  } 

  div{

    padding: 1em;  /* 1em = 28px */

  }

  span{

    font-size:1rem;  /* 1rem = 20px */

    padding: 0.9em;  /* 1em = 18px */

  }

</style>



<html>

  <body>

    <div>   

      <span></span>  

    </div>

  </body>

</html>

在上面的代碼中,我們將根元素(html)的字體大小font-size設爲20px,body的字體大小設爲1rem,那麼轉換爲像素就是28px(20 × 1.4),接着我們又將div的padding設爲1em,由於其基於父元素,所以轉換爲像素是28px ( 28 × 1),然後我們又將span的字體大小設爲1rem,也就是20px,由於其自身設置了字體大小,所以padding設爲1em,轉換爲像素是20px(20 × 1),而不是乘以其父元素的字體大小28px(28 × 1)。

 

注意:當元素自身設置了字體大小,那麼如果它的其他css屬性也使用em單位,則會基於它自身的字體大小。(就像上面例子的span的padding一樣)

 

基於上面這些原因,個人更傾向於使用rem,因爲em使用不當的話,當出現多層繼承時,會很容易混淆,比如:


<style>

  html{ font-size: 20px; }

  body{ 

    font-size: 0.9em;  /* 1rem = 18px */

  } 

  div{

    font-size: 0.8em;  /* 1em = 14.4px */

  }

  span{

    font-size: 0.9em;  /* 1rem = 12.96px */

  }

</style>



<html>

  <body>

    <div>   

      <span></span>  

    </div>

  </body>

</html>

看到沒有,使用em時,如果其祖先元素都是用了em,那麼就會像上面一樣,body繼承其父元素html的字體大小,而div又繼承其父元素body的字體大小,而span又繼承其父元素div的字體大小,最終span的字體大小最終是12.96px(20 × 0.9 ×0.8 × 0.9)。

 

而rem總是相對於根元素(html)的,也就是說,不管哪裏使用了rem單位,都是根元素的字體大小 × 數字,由瀏覽器轉爲像素值。

 

對於rem的兼容性,無須擔心,點擊查看:兼容性

 

當然,em和rem各有優缺點,簡單的使用規則:

  • 如果這個屬性根據它的font-size進行測量,則使用em
  • 其他的一切事物屬性均使用rem.

 

兩者都不使用的情況:

  • 多列布局,一般使用百分比%

 

這裏提供了一個px、em、rem單位的轉換工具:http://pxtoem.com/

 

 

實際使用場景

「rem」是指根元素(root element,html)的字體大小,從遙遠的 IE6 到版本到 Chrome 他們都約好了,根元素默認的 font-size 都是 16px。

rem是通過根元素進行適配的,網頁中的根元素指的是html我們通過設置html的字體大小就可以控制rem的大小;

<script>
    (function(){
        var a=document.documentElement.clientWidth||document.body.clientWidth;
        if(a>460){a=460}
        else{
            if(a<320){a=320}
        }
        document.documentElement.style.fontSize=(a/7.5)*1+"px"})();
</script>

如果是750px的設計稿,但是手機是375px的屏幕:

對應750的設計稿                              視覺稿測量100px-->1rem

375屏幕手機(是750的一半)    頁面顯示爲  50px-->1rem

所以1rem和px對應關係是 50倍 對於 : 屏幕寬度/7.5=375/7.5=50px ;

這樣1rem*50=50px(50px是375屏幕上的長度,相當於750上的100px);

============================================================

如果是375px的設計稿,手機是375px的屏幕:

對應375的設計稿                              視覺稿測量100px-->1rem

375屏幕手機                                頁面顯示爲 100px-->1rem

所以1rem和px對應關係是100倍 對於:  (屏幕寬度/7.5)*2=(375/7.5)*2=100px ;

這樣1rem*100=100px(100px是375屏幕上的長度,相當於350上的100px);

============================================================

綜上所述,對於750的設計稿,375的手機和設計稿是50%的關係,所以設計稿上100px,

對應着375手機上的50px;也就是1rem對應着50px;

document.documentElement.style.fontSize=(a/7.5)*1+"px"

對於375的設計稿,375的手機和設計稿是100%的關係,所以設計稿上100px,

對應着375手機上的100px;也就是1rem對應着100px;

document.documentElement.style.fontSize=(a/7.5)*2+"px"

 

補充說明

爲什麼要使用rem


之前有些適配做法,是通過js動態計算viewport的縮放值(initial-scale)。

例如以屏幕320像素爲基準,設置1,那屏幕375像素就是375/320=1.18以此類推。

但直接這樣強制頁面縮放過於粗暴,會導致頁面圖片文字失真模糊。

Px是相對固定單位,字號大小直接被定死,所以用戶無法根據自己設置的瀏覽器字號而縮放,em和rem雖然都是相對單位,但em是相對於它的父元素的font-size,頁面層級越深,em的換算就越複雜,而rem是直接相對於根元素,這就避開了很多層級關係。移動端新型瀏覽器對rem的兼容很好,可以放心使用。

通用換算和一些坑


有時我們會看到有些使用rem的頁面裏會先給頁面根元素一個樣式:

html {font-size: 62.5%; /*10 ÷ 16 × 100% = 62.5%*/}

爲什麼是62.5%?

大多數瀏覽器的默認字號是16px,因此1rem=16px,這樣不方便我們px和rem的換算,假設1rem=10px,那麼100px=10rem,25px=0.25rem。這樣就好換算很多,於是就有了上面的10/16。

如果是640的設計稿,需要除以2轉化爲和iphone5屏幕等寬的320。所以設計稿px單位/2/10轉爲rem。之後再媒體查詢設置每個屏幕大小的font-size百分比,頁面會根據上面設置的根font-size適配。

看到這裏是不是覺得一切很完美?然而,這裏面有兩個深坑

1.我看了網上很多關於rem的資料,基本都說瀏覽器的默認字號就是16px,然後直接定義font-size:62.5%。但是,rem屬於css3的屬性,有些瀏覽器的早期版本和一些國內瀏覽器的默認字號並不是16px,那麼上面的10/16換算就不成立,直接給html定義font-size: 62.5%不成立。

2.chrome強制字體最小值爲12px,低於12px按12px處理,那上面的1rem=10px就變成1rem=12px,出現偏差(下面給demo)。

解決方案: 將1rem=10px換爲1rem=100px(或者其它容易換算的比例值);不要在pc端使用rem。

那麼上面的頁面根元素樣式要改爲:

html {font-size: 625%; /*100 ÷ 16 × 100% = 625%*/}

再用本工廠總結得出的各分辨率媒體查詢換算:

@media screen and (min-width:360px) and (max-width:374px) and (orientation:portrait) {
    html { font-size: 703%; }
}
@media screen and (min-width:375px) and (max-width:383px) and (orientation:portrait) {
    html { font-size: 732.4%; }
}
@media screen and (min-width:384px) and (max-width:399px) and (orientation:portrait) {
    html { font-size: 750%; }
}
@media screen and (min-width:400px) and (max-width:413px) and (orientation:portrait) {
    html { font-size: 781.25%; }
}
@media screen and (min-width:414px) and (max-width:431px) and (orientation:portrait){
    html { font-size: 808.6%; }
}
@media screen and (min-width:432px) and (max-width:479px) and (orientation:portrait){
    html { font-size: 843.75%; }
}

至此,坑填完。設計稿px換算直接/100即可得到rem值。

更精準健壯的換算


然而,上面的625%大法除了有兼容性問題,也無法很好地根據不同設計稿精準適配,不是我們的最佳選擇。網易和淘寶分別有自己的一套適配方法,適配性也很完美。

  • 網易手機端:技術分享技術分享技術分享基準值: 可以看到,無論頁面以哪種手機比例縮放,body的width都是7.5rem。很明顯,目前網易的手機端設計稿是基於iPhone6,750(設計師給的設計稿是物理分辨率,會是我們寫樣式的邏輯分辨率的兩倍,如果給的設計稿是640,那麼是基於iPhone5,320),且基準值是100px(750/7.5=100)。這個基準值很關鍵,後面的css換算,都和這個基準值有關。動態font-size: 我們看到圖1、圖2、圖3的font-size都有根據屏幕大小而動態改變,可以推算出公式:

    屏幕寬度/設計稿rem寬度=頁面動態font-size值(如:375/7.5=50)

    獲取到這個值,再賦給html元素的style:

    document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + ‘px‘;
    

    這樣就設置好了每個頁面的根fonts-size,因爲rem單位是基於根font-size,因此只要確定一種設計稿對應手機的換算,其餘屏幕尺寸均可自動適配。

    上面我們得出設計稿換算rem的基準值是100,因此只需要把設計稿上的px值除以100即爲我們要的rem值。

    > Px/100=rem,所以100px=1rem,25px=0.25rem
    
  • 淘寶手機端:  大名鼎鼎的Flexible

    資料引用

    大漠:使用Flexible實現手淘H5頁面的終端適配

    齊神:flexible解讀及應用

     

    很多大神包括我們公司同事都有對此適配方案做了解析,所以我這邊簡單綜述:

    引入: 直接引用阿里的CDN文件(或下載到本地引入)

    <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
    

    設定: 頁面不要設定 。Flexible會自動設定每個屏幕寬度的根font-size、動態viewport、針對Retina屏做的dpr。

    換算: 假設拿到的設計稿和上述網易的一樣都是750,Flexible會把設計稿分爲10份,可以理解爲頁面width=10rem,即1rem=75px,所以根font-size(基準值)=75px。

之後的css換算rem公式爲:

px/75=rem,所以100px=100/75=1.33rem,50px=50/75=0.66rem

換算工具


顯然,可以看出px與rem的換算因爲基準值的不同而有些複雜,甚至需要藉助計算器的輔助。在這裏推薦一個換算神器:cssrem

安裝好之後,做一些設置

px_to_rem - px轉rem的單位比例,假設拿到設計稿750,基準值是75,此處就設75

max_rem_fraction_length - px轉rem的小數部分的最大長度。默認爲6。

available_file_types - 啓用此插件的文件類型。[".css", ".less", ".sass", ".scss"]。技術分享

上述三種換算方案的步驟和優劣


  • 通用方案

1、設置根font-size:625%(或其它自定的值,但換算規則1rem不能小於12px)

2、通過媒體查詢分別設置每個屏幕的根font-size

3、css直接除以2再除以100即可換算爲rem。

優:有一定適用性,換算也較爲簡單。

劣:有兼容性的坑,對不同手機適配不是非常精準;需要設置多個媒體查詢來適應不同手機,單某款手機尺寸不在設置範圍之內,會導致無法適配。

  • 網易方案

1、拿到設計稿除以100,得到寬度rem值

2、通過給html的style設置font-size,把1裏面得到的寬度rem值代入x  document.documentElement.style.fontSize = document.documentElement.clientWidth / x + ‘px‘;

3、設計稿px/100即可換算爲rem

優:通過動態根font-size來做適配,基本無兼容性問題,適配較爲精準,換算簡便。

劣:無viewport縮放,且針對iPhone的Retina屏沒有做適配,導致對一些手機的適配不是很到位。

 

網易rem方案:

 

前提:

 

<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">

優勢:

  不用管DPR,只需知設計稿寬度

 

已知:

  假設現有iPhone6設計稿,寬750px,其中一元素寬150px;

根據DPR值,iPhone6的DPR值爲2,我們可得其中該元素的顯示尺寸:

真實顯示CSS值:

 

 

現在我們用網易方案來解決這個問題:

  首先我們取1rem = 100px爲參考值(這個值可以隨便取,爲何取這個值容後解答)

  可知body的寬度:

 

  又因爲body的寬度爲7.5rem,由“網易公式”可得:

  Html的font-size爲:

 

  Dw爲deviceWidth,即設備寬度,這是整個方案裏唯一動態改變的值

  現我們已知設計稿爲iPhone6,又知iPhone6的設備寬爲375px,

  這時候我們再回頭看:

  html當前設備的font-size:

 

  且:

 

  可知,無形中這步已幫我們作了DPR換算;750px的設計稿,顯示在375px的屏幕要怎樣轉換。

  前面我們取了1rem = 100px,可得該元素寬:150px = 1.5rem,

  又知rem爲其他元素相對根元素(html)的大小

  所以可得當前元素寬度的真實css顯示值爲:1.5rem*50px = 75px;(這裏的75px就跟我們前面理想得到的75px不謀而合了)。

  這邊我們把這個運算再拆解來看:

 

  現再回頭看:就可以知道爲什麼當時要取100px爲參考值,取這個值的意義就是爲了方便運算。

 

 

總結:

  我們只需以iPhone6的設計稿(當前主導的機型),750px寬完成一套頁面,當去到其他設備時,因爲我們用的都是rem值,只需要通過JS動態獲得當前的dw,再通過動態獲取的dw改變html的font-size值,頁面的其他元素也會因爲html的改變而進行等比例縮放。

 

 

步驟:

  1.根據設計稿尺寸完成頁面;

  2.設置meta,控制視口寬度,讓頁面以1:1比例渲染頁面

  3.動態設置html的font-size;

  4.把各元素的px值除以100轉換爲rem(字體除外)

 

網易方案關鍵代碼:

    設置視口: 

<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">

    動態設置html的font-size:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
  • 手淘方案

1、拿到設計稿除以10,得到font-size基準值

2、引入flexible

3、不要設置meta的viewport縮放值

4、設計稿px/ font-size基準值,即可換算爲rem

優:通過動態根font-size、viewpor、dpr來做適配,無兼容性問題,適配精準。

劣:需要根據設計稿進行基準值換算,在不使用sublime text編輯器插件開發時,單位計算複雜。

Demo


下面看看demo

設計稿:基於iPhone5,寬度640。

那麼在開發模式,iphone5是320,所有數值均是設計稿一半大小。

期望效果:在iPhone5中,box1寬高50px,box2寬高125px,字體15px。其他屏幕終端自動適配。

技術分享

1、62.5%方案

可以看出,基於chrome iPhone5的調試,box1寬高是60,box2寬高是150。出現了誤差,就是上文提到字號最小值強制12px的原因。

2、625%方案

比例正常。

3、網易方案

比例正常。

4、手淘方案

比例正常(Retina屏做了縮放)。

到底用哪種換算方案呢?


每個人評判的標準不同。但個人更傾向flexible,動態計算viewport和針對iphone手機的dpr縮放使得頁面適配更加精確,而且手淘頁面用戶訪問量比網易頁面大很多。

移動端有用px的時候嗎?


有。當你的頁面圖片或者某一元素比例要固定,不想進行任何縮放時,rem就不適合了,這時候用px單位,能保證該元素不會因縮放而失真模糊。

 

相關鏈接 

W3Cschool中談談CSS3的長度單位(vh、vw、rem) https://www.w3cschool.cn/lugfe/lugfe-5jo225zh.html (轉載)

rem是怎麼計算的https://www.cnblogs.com/xiaozhumaopao/p/8260447.html(轉載)

前端頁面的適配使用rem換算 https://www.cnblogs.com/annie211/p/8118857.html(轉載)

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