前一陣子遇到一個小問題,在同樣的樣式(主要是寬高邊距之類的)條件下,DIV在移動端和PC端的寬度不一樣,排除了絕大多數樣式的問題,但是有個比較陌生,就是box-sizing,其實經常看到,只不過沒怎么注意過,連具體的值都不知道有哪些,在開發者工具里面試了一下,果然和這個樣式有關,因此查了一些資料並記錄一下。
盒子模型
首先,盒子模型大家都知道,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標准就不太相同,當我們引入了不同的庫之后就要額外甄別這一問題,選擇項目最適合的那種。
