一篇文章帶拿下盒模型BFC渲染機制

走在前端的大道上前端

本篇將本身讀過的相關 盒模型BFC 文章中,對本身有啓發的章節片斷總結在這(會對原文進行刪改),會不斷豐富提煉總結更新。segmentfault

一.常見定位方案

在講 BFC 以前,咱們先來了解一下常見的定位方案,定位方案是控制元素的佈局,有三種常見方案:app

  • 普通流 (normal flow)

    在普通流中,元素按照其在 HTML 中的前後位置至上而下佈局,在這個過程當中,行內元素水平排列,直到當行被佔滿而後換行,塊級元素則會被渲染爲完整的一個新行,除非另外指定,不然全部元素默認都是普通流定位,也能夠說,普通流中元素的位置由該元素在 HTML 文檔中的位置決定。佈局

  • 浮動 (float)

    在浮動佈局中,元素首先按照普通流的位置出現,而後根據浮動的方向儘量的向左邊或右邊偏移,其效果與印刷排版中的文本環繞類似。flex

  • 絕對定位 (absolute positioning)

    在絕對定位佈局中,元素會總體脫離普通流,所以絕對定位元素不會對其兄弟元素形成影響,而元素具體的位置由絕對定位的座標決定。spa

2、BFC 概念

Formatting context(格式化上下文) 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,而且有一套渲染規則,它決定了其子元素將如何定位,以及和其餘元素的關係和相互做用。常見的FC有BFC、IFC,還有GFC和FFC。code

那麼 BFC 是什麼呢?orm

BFC 即 Block Formatting Contexts (塊級格式化上下文),它屬於上述定位方案的普通流。blog

一個BFC的範圍 包含建立該上下文元素的全部子元素,但不包括建立了新BFC的子元素的內部元素。這從另外一方角度說明,一個元素不能同時存在於兩個BFC中。由於若是一個元素可以同時處於兩個BFC中,那麼就意味着這個元素能與兩個BFC中的元素髮生做用,就違反了BFC的隔離做用。ip

具備 BFC 特性的元素能夠看做是隔離了的獨立容器,容器裏面的元素不會在佈局上影響到外面的元素,而且 BFC 具備普通容器所沒有的一些特性。

通俗一點來說,能夠把 BFC 理解爲一個封閉的大箱子,箱子內部的元素不管如何翻江倒海,都不會影響到外部。

3、佈局規則

  1. 內部的Box會在垂直方向上一個接一個的放置
  2. 每一個元素的左外邊距與包含塊的左邊界相接觸(從左向右),即便浮動元素也是如此。(這說明BFC中子元素不會超出他的包含塊,而position爲absolute的元素能夠超出他的包含塊邊界)
  3. 屬於同一個BFC的 兩個相鄰Box的 上下margin會發生摺疊;
  4. BFC的區域不會與float的元素區域重疊(阻止元素被浮動元素覆蓋)
  5. 計算BFC的高度時,浮動子元素也參與計算(清除內部浮動)

4、觸發 BFC

只要元素知足下面任一條件便可觸發 BFC 特性:

  1. body 根元素
  2. 浮動元素:float 除 none 之外的值,如left、right
  3. 絕對定位元素:position (absolute、fixed)
  4. display 爲 inline-block、table-cells、flex
  5. overflow 除了 visible 之外的值 ,如hidden、auto、scroll

注意:有些文章中說HTML能夠觸發BFC,沒有說body,按照上邊介紹的一個BFC的範圍和下邊的案例1 來看,HTML能不能觸發不肯定,可是body是能夠的

5、BFC的特性及應用

1.普通流中兩個相鄰的塊元素 垂直方向上的 margin會摺疊

<style>
.p {  
  width:200px;  
  height:50px;  
  margin:50px 0;  
  background-color:red;  
}  
</style>

<body>
   <div class="p"></div>  
   <div class="p"></div>  
</body>

效果圖是:

clipboard.png

發生外邊距摺疊,是由於他們 同屬於 body這個根元素
讓 它們 不屬於同一個BFC,就能避免外邊距摺疊:

<style>
.wrap {  
  overflow:hidden;  
}
.p {  
  width:200px;  
  height:50px;  
  margin:50px 0;  
  background-color:red; 
}
</style>

<body>
    <div class="p"></div>  
    
    <div class="wrap">  
      <div class="p"></div>  
    </div> 
</body>

效果圖是:

clipboard.png

2.普通流中 父子嵌套關係的2個塊元素 垂直方向上的 margin會摺疊

<style>
        .father {
            width: 200px;
            height: 200px;
            background: skyblue;
        }
        
        .son {
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
  
    <body>
        <div class="father">
            <div class="son"></div>
        </div>
    </body>

clipboard.png

而後,咱們給子元素添加一個margin-top: 50px時

.son {
    width: 100px;
    height: 100px;
    background: red;
    margin-top: 50px;
}

咱們神奇的發現父子元素同時"掉下來了50px",如圖所示

clipboard.png

3.BFC能夠包含浮動的元素(清除浮動)

正常狀況下,浮動的元素會脫離普通文檔流,因此下面的代碼裏:

<style>
.wrap {  
  border: 1px solid #000; 
}
.inner {  
  float: left;
  width: 50px;
  height: 50px; 
  background: #eee;
}
</style>

<body>
    <div class="wrap">
        <div class="inner"></div>
    </div>
</body>

外層的div會沒法包含 內部浮動的div,效果見下圖:

clipboard.png

但若是咱們 觸發外部容器的BFC,根據BFC規範 計算BFC的高度時,浮動元素也參與計算,那麼外部div容器就能夠包裹着浮動元素,因此只要把代碼修改以下:

<style>
.wrap {  
  border: 1px solid #000; 
  overflow:hidden;  
}
.inner {  
  float: left;
  width: 50px;
  height: 50px; 
  background: #eee;
}
</style>

<body>
    <div class="wrap">
        <div class="inner"></div>
    </div>
</body>

就能夠完成如下效果:

clipboard.png

4.實現2欄自適應佈局

要求左側固定300px,右側自適應的佈局

<style>
        .wrapper, * {
            padding: 0;
            margin: 0;
        }

        .left {
            width: 300px;
            height: 100px;
            background: red;
            float: left;
        }

        .right {
            height: 100px;
            background: skyblue;
            overflow: hidden;
        }

    </style>
    
    <div class="wrapper">
        <div class="left">left</div>
        <div class="right">right</div>
    </div>

clipboard.png

原理:BFC元素不會和浮動的元素重疊

參考文章:
10 分鐘理解 BFC 原理
CSS中重要的BFC
淺析CSS裏的 BFC 和 IFC
前端人人都應該理解的盒模型BFC渲染機制

相關文章
相關標籤/搜索