BFC和IFC


Box: CSS布局的基本單位

  Box 是 CSS 布局的對象和基本單位, 直觀點來說,就是一個頁面是由很多個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),因此Box內的元素會以不同的方式渲染。讓我們看看有哪些盒子:

  • BFC  快級格式化上下文 block-level box:display 屬性為 block, list-item, table 的元素,會生成 block-level box。並且參與 block fomatting context;                         (塊元素參與BFC)
  • IFC  內聯格式化上下文   inline-level box:display 屬性為 inline, inline-block, inline-table 的元素,會生成 inline-level box。並且參與 inline formatting context;        (行內元素參與IFC)
  • run-in box: css3 中才有, 這兒先不講了。

Formatting context 是 W3C CSS2.1 規范中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。最常見的 Formatting context 有 Block fomatting context (簡稱BFC)和 Inline formatting context (簡稱IFC)。

一、什么是BFC

BFC  (Block formatting context直譯為"塊級格式化上下文")   它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何布局,並且與這個區域外部毫不相干。通俗地講,BFC是一個容器,用於管理塊級元素。

二、如何創建BFC

  • float為 left|right
  • overflow為 hidden|auto|scroll
  • display為 table-cell|table-caption|inline-block|inline-flex|flex
  • position為 absolute|fixed
  • 根元素

三、BFC布局規則:

  • 內部的Box會在垂直方向,一個接一個地放置(即塊級元素獨占一行)。
  • BFC的區域不會與float box重疊(利用這點可以實現自適應兩欄布局)。
  • 內部的Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊(margin重疊三個條件:同屬於一個BFC;相鄰;塊級元素)。
  • 計算BFC的高度時,浮動元素也參與計算。(清除浮動 haslayout)
  • BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。

四、 BFC有哪些特性

特性1:BFC會阻止垂直外邊距折疊

按照BFC的定義,只有同屬於一個BFC時,兩個元素才有可能發生垂直margin的重疊,這個包括相鄰元素或者嵌套元素,只要他們之間沒有阻擋(比如邊框、非空內容、padding等)就會發生margin重疊。

①相鄰兄弟元素margin重疊問題

<style>
p{
        color: #fff;
        background: #888;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
  }
</style>
<body>
    <p>ABC</p>
    <p>abc</p>
</body>

相鄰兄弟元素margin重疊問題

上面兩個p元素同在一個BFC容器(這里指body)下,且是相鄰的塊元素,發送margin重疊
上面例中兩個P元素之間距離本該為200px,然而實際上只有100px,發生了margin重疊。遇到這種情形,我們如何處理?
只需要在p外面包裹一層容器,並觸發該容器生成一個BFC。那么兩個P便不屬於同一個BFC,就不會發生margin重疊了。

下面在第二個p元素外,再包裹一層容器。或者可以兩個p元素外都包裹一層容器。

<style>
p{
        color: #fff;
        background: #888;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
.wrap{
  overflow:hidden;
}
</style>
<body>
   <p>ABC</p>
  <div class="wrap">
    <p>abc</p>
  </div>
</body>

bug修補后

②父子元素margin重疊問題

<style>
.box{
width:100px;
height:100px;
background:#ccc;
}
.wrap {
  background:yellow;
}
.wrap h1{
  background:pink;
  margin:40px;
}
</style>
<body>
<div class="box">box</div>
<div class="wrap">
  <h1>h1</h1>
</div>
</body>

父子元素margin重疊問題
上圖wrap元素與h1元素之間l理論上本該有個40px的上下margin值,然而實際上父子元素並沒有存在margin值,與此同時,兩個div元素的間距為40px。遇到這種情形,我們如何處理?
處理方法其實有很多,**在wrap元素中添加:overflow:hidden;或者overflow:auto;使其父元素形成一個BFC;也可以在wrap元素中添加border:1px solid;或是padding:1px;**這些都可以有效解決父子元素margin重疊問題。

bug修補后

 

特性2:BFC不會重疊浮動元素

利用這個特性,我們可以創造自適應兩欄布局。

<style>
.box1{
  height: 100px;
  width: 100px;
  float: left;
  background: lightblue;
}
.box2{width: 200px;
  height: 200px;
  background: #eee;
}
</style>
<body>
<div class="box1">我是一個左浮動的元素</div>
<div class="box2">喂喂喂!大家不要生氣嘛,生氣會犯嗔戒的。悟空你也太調皮了,
我跟你說過叫你不要亂扔東西,你怎么又……你看,我還沒說完你就把棍子給扔掉了!
月光寶盒是寶物,你把它扔掉會污染環境,要是砸到小朋友怎么辦,就算砸不到小朋友,
砸到花花草草也是不對的。</div>
</body>

文字圍繞浮動元素排列
上圖中,文字圍繞着浮動元素排列,不過在這里,這顯然不是我們想要的。此時我們可以為.box2元素的樣式加上overflow:hidden;使其建立一個BFC,讓其內容消除對外界浮動元素的影響。

自適應布局
這個方法可以用來實現兩列自適應布局,效果不錯,此時左邊的寬度固定,右邊的內容自適應寬度。如果我們改變文字的大小或者左邊浮動元素的大小,兩欄布局的結構依然沒有改變!

 

特性3:BFC可以包含浮動----清除浮動

我們都知道浮動會脫離文檔流,接下來我們看看下面的例子:

<style>
.box1{
  width:100px;
  height:100px;
  float:left;
  border: 1px solid #000;
}
.box2{
  width:100px;
  height:100px;
  float:left;
  border: 1px solid #000;
}
.box{
  background:yellow
}
</style>
<body>
<div class="box">
  <div class="box1"></div>
  <div class="box2"></div>
</div> 
</body>

出現bug

由於容器內兩個div元素浮動,脫離了文檔流,父容器內容寬度為零(即發生高度塌陷),未能將子元素包裹住。解決這個問題,只需要把把父元素變成一個BFC就行了。常用的辦法是給父元素設置overflow:hidden。

修補后

參考文章

【CSS】深入理解BFC原理及應用

10 分鍾理解 BFC 原理

 

補充IFC

IFC Inline Formatting Contexts,也就是“內聯格式化上下文”。

符合以下任一條件即會生成一個IFC

  • 塊級元素中僅包含內聯級別元素

形成條件非常簡單,需要注意的是當IFC中有塊級元素插入時,會產生兩個匿名塊將父元素分割開來,產生兩個IFC,這里不做過多介紹。

IFC布局規則

  • 子元素水平方向橫向排列,並且垂直方向起點為元素頂部。
  • 子元素只會計算橫向樣式空間,【padding、border、margin】,垂直方向樣式空間不會被計算,【padding、border、margin】。
  • 在垂直方向上,子元素會以不同形式來對齊(vertical-align)
  • 能把在一行上的框都完全包含進去的一個矩形區域,被稱為該行的行框(line box)。行框的寬度是由包含塊(containing box)和與其中的浮動來決定。
  • IFC中的“line box”一般左右邊貼緊其包含塊,但float元素會優先排列。
  • IFC中的“line box”高度由 CSS 行高計算規則來確定,同個IFC下的多個line box高度可能會不同。
  • 當 inline-level boxes的總寬度少於包含它們的line box時,其水平渲染規則由 text-align 屬性值來決定。
  • 當一個“inline box”超過父元素的寬度時,它會被分割成多個boxes,這些 oxes 分布在多個“line box”中。如果子元素未設置強制換行的情況下,“inline box”將不可被分割,將會溢出父元素。

相比較於BFC,IFC的規則噼里啪啦一大堆,很少有人會耐心看下去,舉幾個例子,花幾分鍾就可以大概明白其特性。

很多時候,上下間距不生效可以使用IFC來解釋

.warp { border: 1px solid red; display: inline-block; } .text { margin: 20px; background: green; }
<div class="warp"> <span class="text">文本一</span> <span class="text">文本二</span> </div>

clipboard.png
左右margin撐開,上下margin並未撐開,符合IFC規范,只計算橫向樣式控件,不計算縱向樣式空間。

多個元素水平居中

.warp { border: 1px solid red; width: 200px; text-align: center; } .text { background: green; }
<div class="warp"> <span class="text">文本一</span> <span class="text">文本二</span> </div>

clipboard.png

水平排列規則根據IFC容器的text-align值來排列,可以用來實現多個子元素的水平居中。

float元素優先排列

.warp { border: 1px solid red; width: 200px; } .text { background: green; } .f-l { float: left; }
<div class="warp"> <span class="text">這是文本1</span> <span class="text">這是文本2</span> <span class="text f-l">這是文本3</span> <span class="text">這是文本4</span> </div>

clipboard.png
IFC中具備float屬性值的元素優先排列,在很多場景中用來在文章段落開頭添加“tag”可以用到。

最后總結

利用IFC還可以做很多其他的事情,例如:解決元素垂直居中、多個文本元素行高不一致排列混亂。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM