1. 程式人生 > >關於padding在width中的計算——box-sizing

關於padding在width中的計算——box-sizing

目錄

  • 盒子模型
  • 與box-sizing有什麼關係
  • 我們為什麼要開歷史的“倒車”
  • bootstrap怎麼解決的
  • 控制元件的box-sizing
  • 注意甄別

前一陣子遇到一個小問題,在同樣的樣式(主要是寬高邊距之類的)條件下,DIV在移動端和PC端的寬度不一樣,排除了絕大多數樣式的問題,但是有個比較陌生,就是box-sinzing,其實經常看到,只不過沒怎麼注意過,連具體的值都不知道有哪些,在開發者工具裡面試了一下,果然和這個樣式有關,因此查了一些資料並記錄一下。

盒子模型

首先,盒子模型大家都知道,W3C標準的Box Model由四部分組成——content、padding、border、margin

Every box is composed of four parts (or areas), defined by their respective edges: the content edge, padding edge, border edge, and margin edge.

如果我們給一個應用了標準盒模型的div設定一個寬度,那麼,實際上我們設定的是上文提到的content的寬度,也就是下圖這個樣子

  • Element空間高度 = content height + padding + border + margin

還有個不那麼“標準”的盒模型,就是IE6以下(也就是處於Quirks怪異模式)的瀏覽器所使用的,在這種情況下:

  • Element空間寬度 = content Width + margin (Width包含了元素內容寬度、邊框寬度、內距寬度)

這個時候如果我們給div設定一個寬度,那就是為元素的內容+邊框+內邊距設定了一個總值,如圖所示

上面張圖片都使用以下這段程式碼

div {
    width: 200px;
    height: 100px;
    margin: 40px;
    padding: 20px;
    border: 10px solid blue;
}

與box-sizing有什麼關係

通過box-sizing這個樣式我們可以改變這種寬度計算方式,它的屬性值有兩個:content-box和border-box。預設值為content-box,也就是標準的盒子模型,此時的計算公式為

  • width = 內容的寬度
  • height = 內容的高度

另一個屬性為border-box,它的width和height屬性包括內容,內邊距和邊框,但不包括外邊距。看到這裡相信大家都已經明白了,我們用了一個新的屬性重現了一個不太“標準”的標準,被設定為border-box的元素在計算寬高時使用的就是IE6的模式。

我們為什麼要開歷史的“倒車”

其實也不能那麼說,只是繞了一圈之後時間又證明了哪一種方式更合理而已,也並沒有誰對誰錯的問題,那麼這種計算寬高的模式好在哪裡呢?我們舉個簡單的例子

<div id="container">
    <div id="header" class="content_box">
        header
    </div>
    <div id="left" class="content_box">
        left
    </div>
    <div id="right" class="content_box">
        right
    </div>
    <div style="clear: both;"></div>
    <div id="footer" class="content_box">
        footer
    </div>
</div>
.content_box {
    height: 48px;
}

#container {
    width: 480px;
    background: yellow;
}

#left {
    width: 120px;
    background: red;
    float: left;
}

#right {
    width: 360px;
    background: blue;
    float: left;
}

這種左右佈局的應用可以說十分廣泛,並且看起來很直觀且合理,但是如果我們隨便在left或right中加1px的內邊距或border,整個佈局就會被破壞,原因很好理解,按我們上面所說,現代瀏覽器預設是content-box模式,設定的寬度是內容的寬度,當我們增加了padding或者border的時候,left+right就不再是120+360=480了,而是120+360+1=481,由於容器的寬度不夠,div就會自動換到下一行,就變成了現在這個樣子:

bootstrap怎麼解決的

說到這裡,已經有人開始想了,為什麼以前沒有發現這個問題,我也是最近才遇到這種情況,因為bootstrap已經預先重置了預設的box-sizing,而很多元件又是以bootstrap為基底來做文章,所以即使我們不知道box-sizing這一樣式,很可能也已經熟悉了這種模式。

* {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}
*:before,
*:after {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}

另外,bootstrap並不是在所有地方都用border-box,在一些特定元素上還是使用content-box

hr {
  height: 0;
  -webkit-box-sizing: content-box;
     -moz-box-sizing: content-box;
          box-sizing: content-box;
}

input[type="checkbox"],
input[type="radio"] {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
  padding: 0;
}

控制元件的box-sizing

當看到bootstrap對控制元件單獨設定box-sizing時我產生一些疑問,控制元件的預設box-sizing難道不一樣嗎?事實證明確實不一樣,以常見的text和button來說,text預設就是content-box,而button則是border-box,這就不難理解為什麼有時候我們給不同的控制元件設定同樣的寬高卻又無法對齊,這也是box-sizing在作祟。

注意甄別

不過對於這一樣式也有分歧,所以不同的樣式庫使用box-sizing標準就不太相同,當我們引入了不同的庫之後就要額外甄別這一問題,選擇專案最適合的那種。

參考資料:
關於padding值不包含在width裡面的問題,可能和box-sizing有關

box-si