理解CSS-BFC概念

前言

BFC 已是一個耳聽熟聞的詞語了,可是我對於BFC的概念以及應用場景一直都不是很明白,聽說搞懂BFC可讓咱們理解CSS中某些本來詭異的地方。今天着重去了解了一下,作了如下總結。
css

1、文檔流

在解釋BFC以前,先說一下文檔流。咱們常說的文檔流其實分爲定位流浮動流普通流三種。而普通流其實就是指BFC中的FC。
html

FC(Formatting Context),直譯過來就是「格式化上下文」,它是頁面中的一塊渲染區域,有一套渲染規則,決定了其子元素如何佈局,以及和其餘元素之間的關係和做用。常見的FC有BFC(塊級格式化上下文)IFC(行級格式化上下文)、GFC(網格佈局格式化上下文)FFC(自適應格式化上下文)。本文着重介紹BFC,其他的就不在這裏深刻展開了
jquery

2、文檔流的定位方案

【1】常規流(Normal flow)git

  • 在常規流中,盒一個接着一個排列;
  • 在塊級格式化上下文裏面, 它們豎着排列;
  • 在行內格式化上下文裏面, 它們橫着排列;
  • 當position爲static或relative,而且float爲none時會觸發常規流;
  • 對於靜態定位(static positioning),position: static,盒的位置是常規流佈局裏的位置;
  • 對於相對定位(relative positioning),position: relative,盒偏移位置由top、bottom、left、right屬性定義。即便有偏移,仍然保留原有的位置,其它常規流不能佔用這個位置。

【2】浮動(Floats)github

  • 左浮動元素儘可能靠左、靠上,右浮動同理
  • 這致使常規流環繞在它的周邊,除非設置 clear 屬性
  • 浮動元素不會影響塊級元素的佈局
  • 但浮動元素會影響行內元素的佈局,讓其圍繞在本身周圍,撐大父級元素,從而間接影響塊級元素佈局
  • 最高點不會超過當前行的最高點、它前面的浮動元素的最高點
  • 不超過它的包含塊,除非元素自己已經比包含塊更寬
  • 行內元素出如今左浮動元素的右邊和右浮動元素的左邊,左浮動元素的左邊和右浮動元素的右邊是不會擺放浮動元素的

【3】絕對定位(Absolute positioning)瀏覽器

  • 絕對定位方案,盒從常規流中被移除,不影響常規流的佈局;
  • 它的定位相對於它的包含塊,相關CSS屬性:top、bottom、left、right;
  • 若是元素的屬性position爲absolute或fixed,它是絕對定位元素;
  • 對於position: absolute,元素定位將相對於上級元素中最近的一個relative、fixed、absolute,若是沒有則相對於body;

2、BFC是什麼?

MDN上的解釋:塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是佈局過程當中生成塊級盒子的區域,也是浮動元素與其餘元素的交互限定區域。
app

BFC(Block Formatting Context)直譯爲「塊級格式化上下文」,是用於佈局塊級盒子的一塊渲染區域。它規定了內部的塊級如何佈局,而且與這個區域外部絕不相干。簡單的歸納爲:所謂的BFC就是CSS佈局的一個概念,是一塊區域,一個環境。
ide

3、BFC觸發方式

上文提到BFC是一塊渲染區域,那這塊渲染區域到底在哪,它有多大,這些由生成BFC的元素決定,CSS2.1中規定知足下列CSS聲明之一的元素便會生成BFC。
wordpress

【1】根元素,即HTML元素佈局

【2】浮動元素:float值爲leftright

【3】overflow值不爲 visible,爲 autoscrollhidden

【4】display的值爲inline-blockinltable-celltable-captiontableinline-tableflexinline-flexgridinline-grid

【5】position的值爲absolutefixed   

4、瀏覽器對BFC的約束規則

【1】內部的Box會在垂直方向上一個接一個的放置

【2】垂直方向上的距離由margin決定。(完整的說法是:屬於同一個BFC的兩個相鄰Box的margin會發生重疊(塌陷),與方向無關。)

【3】每一個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便浮動元素也是如此。(這說明BFC中子元素不會超出他的包含塊,而position爲absolute的元素能夠超出他的包含塊邊界)

【4】BFC的區域不會與float的元素區域重疊

【5】計算BFC的高度時,浮動子元素也參與計算

【6】BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面元素,反之亦然

5、 BFC在佈局中的應用

BFC是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面元素,反之亦然。咱們能夠利用BFC的這個特性來作不少事。

【1】防止margin重疊(塌陷)


根據BFC佈局規則第【2】條:垂直方向上的距離由margin決定。(完整的說法是:屬於同一個BFC的兩個相鄰Box的margin會發生重疊(塌陷),與方向無關。)兩個p元素之間的距離應該爲(50+50)px,發生了margin重疊後,兩個p之間的距離爲50px

解決:咱們能夠在其中一個p外面包裹一層容器,並觸發該容器生成一個新BFC。那麼兩個P便不屬於同一個BFC,就不會發生margin重疊了。

<style> p { color: rgba(21, 22, 22, 0.972); background: rgb(231, 105, 2); width: 200px; line-height: 100px; text-align:center; margin: 50px; font-weight: bold; } </style> <body> <p>Hello</p> <p>Hi</p> </body>複製代碼
<style> .wrap { /* 新的BFC */ overflow: hidden; } </style>複製代碼

【2】清除內部浮動

根據BFC佈局規則第【5】條:計算BFC的高度時,浮動子元素也參與計算。parent內部元素浮動了,所以div的高度就坍塌了,要解決坍塌,就得清除浮動。

解決:爲達到清除內部浮動,咱們能夠觸發parent生成BFC,那麼parent在計算高度時,parent內部的浮動元素child也會參與計算。

<style> .parent { border: 5px solid rgb(231, 105, 2); width: 300px; } .child { border: 5px solid rgba(95, 179, 235, 0.972); width: 100px; height: 100px; float: left; } </style> <body> <div class="parent"> <div class="child"></div> <div class="child"></div> </div> </body>複製代碼
<style> .parent { border: 5px solid rgb(231, 105, 2); width: 300px; /* 新的BFC */ overflow: hidden; } </style>複製代碼

【3】自適應多欄佈局

根據BFC佈局規則第【3】條:每一個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便浮動元素也是如此。  所以,雖然存在浮動的元素aslide,但main的左邊依然會與包含塊的左邊相接觸。

解決:咱們能夠經過經過給main設置overflow:hidden來觸發main生成BFC, 當觸發main生成BFC後,這個新的BFC不會與浮動的aside重疊。所以會根據包含塊的寬度,和aside的寬度,自動變窄。從而實現自適應兩欄佈局。

<style> body { width: 400px; position: relative; } .aside { width: 100px; height: 150px; float: left; background: rgb(48, 44, 44); } .main { height: 200px; background: rgb(194, 189, 189); } </style> <body> <div class="aside"></div> <div class="main"></div> </body>複製代碼
<style> .main { /* 新的BFC */ overflow: hidden; height: 200px; background: rgb(194, 189, 189); } </style>複製代碼

【4】用於佈局

聖盃佈局和雙飛翼佈局,他們的都要求三列布局,中間寬度自適應,兩邊定寬,這樣作的優點是重要的東西放在文檔流前面能夠優先渲染。詳情連接:聖盃佈局&&雙飛翼佈局


<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script> </head> <style> body { min-width: 550px; font-weight: bold; font-size: 20px; } #header, #footer { background: rgba(29, 27, 27, 0.726); text-align: center; height: 60px; line-height: 60px; } #footer { clear: both; } #container { padding-left: 200px; padding-right: 150px; overflow: hidden; } #container .column { position: relative; float: left; text-align: center; height: 300px; line-height: 300px; } #center { width: 100%; background: rgb(206, 201, 201); } #left { width: 200px; right: 200px; margin-left: -100%; background: rgba(95, 179, 235, 0.972); } #right { width: 150px; margin-right: -150px; background: rgb(231, 105, 2); } </style> <body> <div id="header">#header</div> <div id="container"> <div id="center" class="column">#center</div> <div id="left" class="column">#left</div> <div id="right" class="column">#right</div> </div> <div id="footer">#footer</div> </body> </html>複製代碼

參考:

  1. CSS深刻理解流體特性和BFC特性下多欄自適應佈局​​​​​​​
  2. 史上最全面、最透徹的BFC原理剖析​​​​​​​
  3. 深刻理解BFC
  4. Understanding Block Formatting Contexts in CSS
  5. BFC 神奇背後的原理
  6. BFC 初體驗​​​​​​​
相關文章
相關標籤/搜索