什麼是盒子模型
當你對一個文件進行佈局(laying out)時候, 瀏覽器引擎會根據CSS-Box模型將所有元素描述為一個盒子, CSS會決定這些盒子的大小, 位置, 屬性(顏色, 邊框...)。
盒模型分類
盒模型分為兩類: IE盒模型和標準盒模型。 兩者的區別在於:
IE盒模型的width/height = content + border + padding
標準盒模型的width/height = content
複製程式碼
IE盒模型

標準盒模型

普通文件流塊元素的CSS外邊距合併問題
<style>
* {
margin: 0;
padding: 0;
}
.demo1 {
width: 40px;
height: 40px;
background: pink;
padding: 10px;
margin: 10px 0;
border: 2px solid pink;
}
.demo2 {
width: 40px;
height: 40px;
padding: 10px;
background: blue;
margin: 20px 0;
border: 2px solid blue;
}
</style>
<div class="demo1"></div>
<div class="demo2"></div>
複製程式碼

可見demo1與demo2的外邊距為20px。而不是30px。
需要注意的是:只有普通文件流中塊框的垂直外邊距才會發生外邊距合併。行內框、浮動框或絕對定位之間的外邊距不會合並。
改變盒子模型
CSS3支援改變盒子模型。
box-sizing
box-sizing用來改變計算盒子高度/寬度的預設盒子模型。可以使用此屬性來模擬不正確支援CSS盒子模型規範的瀏覽器的行為。
/* 關鍵字 值 */
box-sizing: content-box;
box-sizing: border-box;
/* 全域性 值 */
box-sizing: inherit;
box-sizing: initial;
box-sizing: unset;
複製程式碼
content-box(預設值): 標準盒模型
寬度 = 內容的寬度
高度 = 內容的高度
不會包含border, padding。
複製程式碼
demo演示:
.demo1 {
box-sizing: content-box;
width: 40px;
height: 40px;
background: pink;
padding: 10px;
margin: 10px 0;
border: 2px solid pink;
}
<div class="demo1"></div>
複製程式碼
盒子內容寬度就是40px;

border-box: 怪異模式
width = border + padding + 內容的width,
height = border + padding + 內容的height。
複製程式碼
demo演示:
.demo {
box-sizing: border-box;
width: 40px;
height: 40px;
background: pink;
padding: 10px;
margin: 10px 0;
border: 2px solid pink;
}
<div class="demo"></div>
複製程式碼
盒子的內容寬度為16px;

padding-box: 已經棄用
inherit: 規定應從父元素繼承 box-sizing 屬性的值
為什麼要使用border-box
content-box缺點
當你想讓兩個子容器float:left,寬度各50%,然後給一點padding,最後讓子容器並排充滿父容器,一切想的挺美好,然而你發現結果並不是這麼美好,因為子容器的盒子寬度已經超出了父容器的一半,導致了折行,於是,width就不能50%了,只能是50%再減去padding的畫素值
複製程式碼
<style>
* {
margin: 0;
padding: 0;
}
.demo div {
float: left;
width: 50%;
height: 100px;
padding: 0 10px;
}
.demo1 {
background: pink;
}
.demo2 {
background: blue;
}
</style>
<div class="demo">
<div class="demo1"></div>
<div class="demo2"></div>
</div>
複製程式碼

border-box的優勢:
border-box的誕生,主要就是解決content-box的最大缺點。border-box意味著子容器的padding和border的厚度都算在50%之內,這樣,你可以隨意的修改padding和border的厚度值,根本不用擔心父容器被撐爆。
複製程式碼
簡單修改下上述程式碼。
.demo div {
box-sizing: border-box;
float: left;
width: 50%;
height: 100px;
padding: 0 10px;
}
複製程式碼

因此border-box使用場景如下:
子元素有padding和border,或者至少有其一,並且需要給子元素設定100%寬度(或者50%寬度等等),這時候顯然需要border-box。設為border-box之後,padding和border的厚度可以隨意調,並不會溢位父元素。如果是content-box,那麼,寬度必然會溢位,而且,為了不溢位,你設定子元素的寬度就只能是一個定值,或者是一個計算值(比如calc(100% - 20px)。