理解BFC、IFC、GFC、FFC
什麼是fc?
FC的全稱是:Formatting Contexts,是W3C CSS2.1規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。
BFC
Block Formatting Context 叫做“塊級格式化上下文”。BFC的佈局規則如下:
- 內部的盒子會在垂直方向,一個個地放置;
- 盒子垂直方向的距離由margin決定,屬於同一個BFC的兩個相鄰Box的上下margin會發生重疊;
- 每個元素的左邊,與包含的盒子的左邊相接觸,即使存在浮動也是如此;
- BFC的區域不會與float重疊;
- BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素,反之也如此;
- 計算BFC的高度時,浮動元素也參與計算。
介紹過了BFC的佈局規範,再來說說哪些元素會產生BFC。
- 根元素;
- float的屬性不為none;
- position為absolute或fixed;
- display為inline-block,table-cell,table-caption,flex;
- overflow不為visible
接下來說說BFC的作用和原理,首先看看自適應兩欄佈局
我們先定義兩個div:
<div class="aside"></div>
<div class="main"></div>
然後定義css:
div {
width:300px;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: black;
}
.main {
height:200px;
background-color:red;
}
效果圖如下:
這正滿足了規範的第三條:
每個元素的左邊,與包含的盒子的左邊相接觸,即使存在浮動也是如此。
所以如果我們需要將黑色區域撐到紅色的左邊,就需要利用規範的第四條:
BFC的區域不會與float重疊。
也就是說我們需要創造BFC區域。我們通過將紅色區域的overflow設為hidden
.main {
overflow:hidden;
height:200px;
background-color:red;
}
效果如下:
![這裡寫圖片描述](https://img-blog.csdn.net/20170610233213217?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQ3MjgzMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
接下來看看清除內部浮動
首先是父div套子div
<div class="parent">
<div class="child"></div>
</div>
然後是css:
.child {
border:1px solid red;
width:100px;
height:100px;
float:left;
}
.parent {
border:1px solid black;
width:300px;
}
效果如下:
![這裡寫圖片描述](https://img-blog.csdn.net/20170610233357813?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQ3MjgzMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
可以看到,父div壓根就沒有被撐開。
我們再回顧一下BFC規範中的第六條:
**計算BFC的高度時,浮動元素也參與計算**。
所以我們需要將父div觸發為BFC,也就是將其overflow設為hidden:
.parent {
border:1px solid black;
width:300px;
overflow:hidden;
}
效果如下:
![這裡寫圖片描述](https://img-blog.csdn.net/20170610233435893?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQ3MjgzMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
可以看到父div已經撐開了。
再談談margin重疊問題。
先定義兩個垂直的div:
<div class="p"></div>
<div class="p"></div>
然後定義margin:
.p {
width:200px;
height:50px;
margin:50px 0;
background-color:red;
}
可以看到margin重疊後的效果:
我們再看看BFC規範的第二條:
盒子垂直方向的距離由margin決定,屬於用一個BFC的兩個相鄰Box的上下margin會發生重疊。
說明兩者屬於同一個BFC,所以我們需要兩個div**不屬於同一個BFC**。
為第二個div套一個父親div,然後講其overflow設為hidden來啟用一個BFC就可以使margin不再重疊。
<div class="p"></div>
<div class="wrap">
<div class="p"></div>
</div>
.wrap {
overflow:hidden;
}
效果如下:
IFC
IFC佈局規則:
- 框會從包含塊的頂部開始,一個接一個地水平擺放。
- 擺放這些框的時候,它們在水平方向上的外邊距、邊框、內邊距所佔用的空間都會被考慮在內。在垂直方向上,這些框可能會以不同形式來對齊:它們可能會把底部或頂部對齊,也可能把其內部的文字基線對齊。能把在一行上的框都完全包含進去的一個矩形區域,被稱為該行的行框。水平的margin、padding、border有效,垂直無效。不能指定寬高。
- 行框的寬度是由包含塊和存在的浮動來決定。行框的高度由行高計算這一章所描述的規則來決定。
得出結論:
- 一個line box總是足夠高對於包含在它內的所有盒子。然後,它也許比包含在它內最高的盒子高。(比如,盒子對齊導致基線提高了)。
- 當盒子B的高度比包含它的line box的高度低,在line box內的B的垂值對齊線通過’vertical align’屬性決定。當幾個行內級盒子在一個單獨的line box內不能很好的水平放置,則他們被分配成了2個或者更多的垂直重疊的line boxs.因此,一個段落是很多個line boxs的垂直疊加。Line boxs被疊加沒有垂直方向上的分離(特殊情況除外),並且他們也不重疊。
- 通常,line box的左邊緣挨著它的包含塊的左邊緣,右邊緣挨著它的包含塊的右邊緣。然而,浮動盒子也許會在包含塊邊緣和line box邊緣之間。因此,儘管line boxs在同樣的行內格式上下文中通常都有相同的寬度(就是他的包含塊的寬度),但是水平方向上的空間因為浮動被減少了,它的寬度也會變得複雜。Line boxs在同樣的行內格式上下文中通常在高度上是多樣的(比如,一行也許包含了一個最高的圖片然後其他的也可以僅僅只包含文字)
- 當在一行中行內級盒子的總寬度比包含他們的line box的寬度小,他們的在line box中的水平放置位置由’text align’屬性決定。如果屬性是’justify’,使用者代理可能會拉伸空間和文字在inline boxs內。
- 當一個行內盒子超過了line box的寬度,則它被分割成幾個盒子並且這些盒子被分配成幾個橫穿過的line boxs。如果一個行內盒子不能被分割。則行內盒子溢位line box。
- 當一個行內盒子被分割,分割發生則margins,borders,和padding便沒有了視覺效果。
- 在同樣的line box內的行內盒子也許會被分割成幾個盒子因為雙向的文字。
Line boxs在行內格式上下文中檔需要包含行內級內容時被創造。Line boxs包含沒有文字,沒有空格,沒有帶著margins,padding和borders,以及沒有其他在流中的內容(比如圖片,行內盒子和行內表格),也不會以新起一行結尾。對於在他們內的任何盒子的位置都以他們決定並且必須將他們視作沒有高度的line boxs。
主要影響IFC內佈局的css:
font-size
line-height
height
vertical-aligin
line box
行盒模型,這是一個顯示區域,根據塊狀容器內,每一行的多個內聯元素(inline-level element)都會共同生成一個行盒模型。
font-size
常見的屬性,用來指定文字型別節點的大小。IFC內的很多屬性的值是基於這個的。
line-height & height
在一個由多個內聯元素組成的塊狀容器內,’line-height’為內聯元素的行盒模型指定了一個最低高度。 這個最低高度是分別由基線上的最小高度和基線下的最小深度組成。
從上到下四條線分別是頂線、中線、基線、底線。 那麼行高是指上下文字行的基線間的垂直距離,即圖中兩條紅線間垂直距離(實際在數值上,行高也等於其它相同顏色間的距離)。
vertical-align
該屬性影響由多個內聯元素生成的盒模型組成的行內盒模型的垂直定位。
vertical有幾個特定的值,或者指定一個值。
<p class="a1">
<span style="vertical-align:60px;">
English中文
</span>
<span>
中文English
</span>
</p>
給第一個span,設定60px的垂直偏移量,顯示如下:
其中,黃色線就是基線(baseline),綠線和黃線的間隔即為60px。 這裡會發現,容器(藍色)的高度被撐高了。
容器的高度 height = line-height + vertical-align
當然同理,如果容器的高度被指定了,那麼高度則不變,而超出的部分則不影響佈局。如果設定overflow:hidden,超過的部分則不可見。
而vertical-align的其它特殊值,均可以看做一個根據容器高度而變化的相對值。