常规流之块级格式化上下文(Block Formatting Contexts)
在css2.1中,常規流包括塊框(block boxes)的塊格式化(block formatting),行內框(inline boxes)的行內格式化(inline formatting),塊級框(block-level-boxes)或行內級框(inline-level-boxes)的相對定位。常規流中的框屬于一個格式化上下文,可能是塊或者是行內,但不能同時都是。塊級框參與塊級格式化上下文,行內級框參與行內級格式化上下文。今天我們先來說說塊級格式化上下文,也就是我們常說的BFC。
一.形成塊級格式化上下文
- 絕對定位元素(fixed其實是absolute的一個子集)
- display為inline-block,table-cell,table-caption,flex,inline-flex(這里有一點要注意的,display-table本身不會形成BFC,但是它會產生匿名框,其中包含的dispaly:table-cell元素會形成BFC)
- overflow不為visible
- 根元素
- float屬性不為none
這里要說明的是這些是形成塊格式化上下文,而不是說是參與塊級格式化上下文,這兩個概念很容易弄混,大家可以仔細體會下。塊格式化上下文是一個獨立的渲染區域,而且只會有塊級框(block-level box)來參與,它規定內部的塊級框如何布局,與這個區域的外部毫不相干。
二.塊格式化上下文中的特性
? 在塊格式化上下文中,框會一個接一個的被垂直放置,他們的起點是一個包含塊的頂部。
兩個兄弟框之間的垂直距離取決于margin屬性。在BFC中相鄰的塊級元素的垂直邊距會折疊。
在BFC中,每一個元素的左外邊(left margin邊界)與包含塊的左邊相接觸(對于從右到左的格式化,右邊距接觸包含塊右邊)。即使存在浮動也是如此(盡管一個元素的內容區域會由于浮動而壓縮),除非這個元素也形成了一個新的BFC。
計算BFC高度的時候,浮動子元素也會參與計算。
BFC的區域不會與float box重疊。
三.塊級格式化上下文的作用
我們之所以要了解一些東西,無非是需要有現實的意義和作用,不然誰管它(笑)。
那么BFC有什么作用呢,那就得從BFC的特性說起了。下面,我們會根據一些具體的例子來一個個說明。
1.清除浮動
我們上面說了,計算BFC高度的時候,浮動子元素也會參與計算,而浮動子元素造成的塌陷想必大家也都非常了解,那么如果父元素形成了BFC,是不是就可以包含浮動子元素了呢?直接看例子(為了直觀我就不貼可運行代碼了):
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>BFC清除浮動</title><style>*{margin:0; padding: 0;}.wrap-wrap{ height: 150px;}.wrap{ width: 300px; background-color :#fcc; color: #fff;}.son1,.son2{ float: left; width: 100px; height: 100px; background-color:red;}.son2{ background-color:blue; }.wrap-bfc{ overflow: hidden;}</style> </head> <body> <div class="wrap-wrap"><div class="wrap">wrap<div class="son1">son1</div><div class="son2">son2</div></div> </div> <div class="wrap wrap-bfc">wrap<div class="son1">son1</div><div class="son2">son2</div> </div> </body> </html>運行結果如下:
我們通過一個overflow:hidden使下面的wrap形成了BFC,它高度的計算中浮動子元素也會參與,自然就包含了浮動元素,從而達到了清除浮動的目的。當然,不止overflow:hidden可以清除浮動,各位可以自行試試其他屬性。
2.防止垂直margin重疊
在同一BFC中相鄰的塊級元素的垂直邊距會折疊。那么如果這兩個元素不在一個BFC中了會發生什么呢,繼續看例子:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>防止邊距折疊</title><style>*{margin:0; padding: 0;}.wrap,.wrap1,.wrap2{ width: 200px; height: 100px; background-color :#fcc; color: #fff;}.son1,.son2{ width: 50px; height: 20px; margin: 10px; background-color:red;}.son2{ background-color:blue; }.wrap1{ overflow: hidden; background-color:lime; }.wrap2{ overflow: hidden; background-color:lime; }.new-wrap{ overflow: hidden;}</style></head> <body><div class="wrap"><div class="son1">son1</div><div class="son2">son2</div>wrap</div><p>——————分割符————</p><div class="wrap1"><div class="son1">son1</div><div class="son2">son2</div>wrap1</div><p>——————分割符————</p><div class="wrap2"><div class="son1">son1</div><div class="new-wrap"><div class="son2">son2</div></div>wrap2</div> </body> </html>
?
運行結果如下:
這里有兩點要說。
1).wrap1與son1的margin折疊
我們先看wrap,son1是有個margin-top,但是圖中給我們的感覺是沒有,反而是它的父元素wrap有一個margin-top。為什么呢,這個就要看magrin折疊的說明了,這個也是標準中的內容:
In this specification, the expression?collapsing margins?means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.?所有毗鄰的兩個或更多盒元素的margin將會合并為一個margin共享之。毗鄰的定義為:同級或者嵌套的盒元素,并且它們之間沒有非空內容、Padding或Border分隔。
可知嵌套的盒元素也會Collapsing Margins,就不難知道為什么會這樣了。而在wrap1中,同樣的結構,也沒有非空內容、Padding或Border分隔,為什么又不折疊了呢?這里就要知道什么叫毗鄰了:
Two margins are adjoining if and only if:
- both belong to in-flow block-level boxes that participate in the same block formatting context
- no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.)
- both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
- top margin of a box and top margin of its first in-flow child
- bottom margin of box and top margin of its next in-flow following sibling
- bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
- top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero or 'auto' computed 'height', and no in-flow children
我就不一個個翻譯了,就看第一條,這些margin都處于普通流中,并在同一個BFC中。我自己的理解是下面這樣的,不一定正確,如果知道的同學還請指正:
wrap1的overflow:hidden屬性形成了一個新的BFC,son1就參與了這個新的BFC。而wrap1本身是在根元素形成的BFC種,由此兩個就不在同一個BFC中了,也就不是毗鄰的了,自然margin不會折疊。
2).son1與son2的邊距折疊。
根據上面一點說的,son1和son2是滿足margin折疊的條件的,那么如果我們給son2包裹個new-wrap,并讓它形成BFC,自然就沒有邊距折疊了。
?
3.自適應兩欄布局。
這個直接上代碼吧,根據例子來說,比較直觀
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>自適應布局</title><style>*{margin:0; padding: 0;}body {position: relative;color: #fff;}.aside {width: 100px;height: 150px;float: left;background: #f66;}.main {height: 200px;background: #fcc;}</style> </head> <body><div class="aside">float aside</div><div class="main">main</div> </body> </html>運行結果:
這里首先要說的是main的位置問題。在BFC中,每一個元素的左外邊(left margin邊界)與包含塊的左邊相接觸(對于從右到左的格式化,右邊距接觸包含塊右邊),這里雖然有float的aside,但是main的左邊依然與包含塊的左邊接觸。
而如果我們對main設置這樣的樣式:main:overflow:hidden,結果如下:
當觸發main生成BFC后,這個新的BFC不會與浮動的aside重疊。因此會根據包含塊的寬度,和aside的寬度,自動變窄。為什么呢:
BFC的區域不會與float box重疊。
四.總結
今天我們主要分析了什么是BFC、怎么形成BFC以及BFC的作用。其中有一些我總結個人的理解,希望對大家有幫助。另外,在css3的草案中,對這個概念做了改動,將Block?formatting?context?叫做?flow?root,觸發方式也發生了變化:The value of 'position' is neither "static" nor "relative".fixed作為absolute的一個子類也會形成flow root,有興趣的同學可以自己去了解下。好了,就這么多了,我寫東西都是準備好了然后一口氣,后面再一點點修改,初成文難免會有錯漏,還請大家多多指正。下一章會分析下行內級格式化上下文的相關。
?
?
參考:
1.KB010: 常規流( Normal flow )
2.w3c盒模型
3.w3c常規流
4.前端精選文摘:BFC 神奇背后的原理
轉載于:https://www.cnblogs.com/rexD/p/4597380.html
總結
以上是生活随笔為你收集整理的常规流之块级格式化上下文(Block Formatting Contexts)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CString与std::string
- 下一篇: deLPHI书籍名称