- 做者:陳大魚頭
- github: KRISACHAN
The CSS box model describes the rectangular boxes that are generated for elements in the document tree and laid out according to the visual formatting model.CSS盒模型描述了經過 文檔樹中的元素 以及相應的 視覺格式化模型(visual formatting model) 所生成的矩形盒子。javascript
當瀏覽器對一個 render tree 進行渲染時,瀏覽器的渲染引擎就會根據 基礎盒模型(CSS basic box model) ,將全部元素劃分爲一個個矩形的盒子,這些盒子的外觀,屬性由CSS
來決定。css
咱們在瀏覽器控制檯輸入以下代碼就能夠看到頁面的每個元素都是由一個矩形來包裹的,這些就是盒子。html
$$('*').forEach(e => { e.style.border = '1px solid'; })
圖示以下:java
CSS 的 視覺格式化模型(visual formatting model) 是根據 基礎盒模型(CSS basic box model) 將 文檔(doucment) 中的元素轉換一個個盒子的實際算法。官方說法就是: 它規定了用戶端在媒介中如何處理文檔樹( document tree )。git
每一個盒子的佈局由如下因素決定:github
視覺格式化模型(visual formatting model) 的計算,都取決於一個矩形的邊界,這個矩形,被稱做是 包含塊( containing block ) 。 通常來講,(元素)生成的框會扮演它子孫元素包含塊的角色;咱們稱之爲:一個(元素的)框爲它的子孫節點建造了包含塊。包含塊是一個相對的概念。算法
例子以下:瀏覽器
<div> <table> <tr> <td>hi</td> </tr> </table> </div>
以上代碼爲例,div
和 table
都是包含塊。div
是 table
的包含塊,同時 table
又是 td
的包含塊,不是絕對的。微信
圖示:(圖片來自w3help):ide
盒子的生成是 CSS視覺格式化模型 的一部分,用於從文檔元素生成盒子。盒子的類型取決於CSS display
屬性。格式化上下文(formatting context) 是定義 盒子環境 的規則,不一樣 格式化上下文(formatting context) 下的盒子有不一樣的表現。
如下是盒子相關的概念定義:
塊級元素
display
爲 block
、list-item
或 table
時,它就是塊級元素。塊級盒子
匿名盒子
CSS 選擇器
選中,也就是全部可繼承的 CSS 屬性值都爲 inherit
,而全部不可繼承的 CSS 屬性值都爲 initial
。所以稱爲匿名盒子(anonymous boxes)。行內元素
display
爲 inline
、inline-block
或 inline-table
時,它就是行內級元素。行內盒子
行內格式化上下文(inline formatting context)
的建立。匿名行內盒子
initial
。行盒子
run-in 盒子(在CSS 2.1的標準中移除了)
display: run-in
來設置,它既能夠是塊盒子,又能夠是行內盒子,這取決於它後面的盒子的類型。BFC 這個概念來自於 視覺格式化模型(visual formatting model) 中的 正常流(Normal flow)。
浮動、絕對定位元素、塊容器(例如inline-blocks、table-cells、and table-captions)以及溢出而非可視的元素(除非該值已經傳播到了視口)都是創建 BFC(Block formatting contexts) 的條件。
在BFC(Block formatting contexts)中,在包含塊內一個盒子一個盒子不重疊地垂直排列,兩個兄弟盒子直接的垂直距離由margin
決定。浮動也是如此(雖然有可能兩個盒子的距離會由於floats
而變小),除非該盒子再建立一個新的BFC。
魚頭注:簡單來講,BFC就是一個獨立不干擾外界也不受外界干擾的盒子啊(/ω\)。
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含塊的寬度
上面的計算法則是基於 writing-mode: ltr
而言,若是是別的書寫順序,則按照該順序來計算。
若是寬度不是 auto 或者 'border-left-width'+'padding-left'+'width'+'padding-right'+'border-right-width' 的結果大於包含塊的寬度,對於如下規則,被視爲零。
若是隻有一個值指定爲'auto',則其使用的值來自相等。
若是寬度設置爲 auto ,則任何其餘 auto 值變爲 0 ,而且寬度會跟着因此盒子的狀況鋪滿。
若是 'margin-left' 跟 'margin-right' 都爲 auto ,則會使元素相對於包含塊的邊緣水平居中。
若是 'margin-left' 跟 'margin-right' 都爲 auto ,則它們的具體值爲 0 。
若是寬度爲 auto,則使用 shrink-to-fit 的寬度計算方式(CSS 2.2沒有定義精確的算法)。
而後 shrink-to-fit 大概的計算方式則是:min(max(preferred minimum width, available width), preferred width)。
'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含塊的寬度
若是 'left','width' 和 'right' 都是 'auto',則首先將 'margin-left' 和 'margin-right' 的 'auto' 值設置爲 0。
若是 'left','width' 和 'right' 都不是 'auto',則按照實際值來算。
若是 'margin-left' 跟 'margin-right' 都爲 0 ,則根據 'left' ,'width' 和 'right' 的值是不是 'auto' 來計算。 若是 一個方向值 ,'width' 的值是 'auto',而 '另外一個一個方向值' 不是,則寬度使用 shrink-to-fit 算法計算。若是一個值爲'auto'而另外兩個值不算,則該值使用 shrink-to-fit 來計算。
上面的計算法則是基於 writing-mode: ltr
而言,若是是別的書寫順序,則按照該順序來計算。
魚頭注:這裏特別說明一點,在MDN中依然把flexbox跟gridbox 算在 BFC中,但在最新的規範裏,它們已經從BFC中分離了出去,成爲獨立的一個CSS模塊,內容以下:
若是你喜歡探討技術,或者對本文有任何的意見或建議,很是歡迎加魚頭微信好友一塊兒探討,固然,魚頭也很是但願能跟你一塊兒聊生活,聊愛好,談天說地。
魚頭的微信號是:krisChans95
也能夠掃碼添加好友,備註「SF」就行