CSS中重要的BFC

CSS中有個重要的概念BFC,搞懂BFC可讓咱們理解CSS中某些本來詭異(??)的地方。css

感興趣的同窗能夠加文末的微信羣,一塊兒討論吧~html

1. 簡介

在解釋BFC以前,先說一下文檔流。咱們常說的文檔流其實分爲定位流浮動流普通流三種。而普通流其實就是指BFC中的FC。FC(Formatting Context),直譯過來是格式化上下文,它是頁面中的一塊渲染區域,有一套渲染規則,決定了其子元素如何佈局,以及和其餘元素之間的關係和做用。常見的FC有BFC、IFC,還有GFC和FFC。前端

BFC(Block Formatting Context)塊級格式化上下文,是用於佈局塊級盒子的一塊渲染區域。MDN上的解釋:BFC是Web頁面 CSS 視覺渲染的一部分,用於決定塊盒子的佈局及浮動相互影響範圍的一個區域。web

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

2. 三種文檔流的定位方案

常規流(Normal flow)瀏覽器

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

浮動(Floats)微信

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

絕對定位(Absolute positioning)ide

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

3. BFC觸發方式

  1. 根元素,即HTML標籤
  2. 浮動元素:float值爲leftright
  3. overflow值不爲 visible,爲 autoscrollhidden
  4. display值爲 inline-blocktable-celltable-captiontableinline-tableflexinline-flexgridinline-grid
  5. 定位元素:position值爲 absolutefixed

注意 display:table也能夠生成BFC的緣由在於Table會默認生成一個匿名的table-cell,是這個匿名的table-cell生成了BFC。佈局

4. 約束規則

瀏覽器對BFC區域的約束規則:學習

  1. 生成BFC元素的子元素會一個接一個的放置。
  2. 垂直方向上他們的起點是一個包含塊的頂部,兩個相鄰子元素之間的垂直距離取決於元素的margin特性。在BFC中相鄰的塊級元素的外邊距會摺疊(Mastering margin collapsing)
  3. 生成BFC元素的子元素中,每個子元素左外邊距與包含塊的左邊界相接觸(對於從右到左的格式化,右外邊距接觸右邊界),即便浮動元素也是如此(儘管子元素的內容區域會因爲浮動而壓縮),除非這個子元素也建立了一個新的BFC(如它自身也是一個浮動元素)。

規則解讀:

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

5. 做用

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

5.1 阻止元素被浮動元素覆蓋

一個正常文檔流的block元素可能被一個float元素覆蓋,擠佔正常文檔流,所以能夠設置一個元素的float、display、position值等方式觸發BFC,以阻止被浮動盒子覆蓋。

使用BFC阻止元素被浮動元素覆蓋

5.2 能夠包含浮動元素

經過改變包含浮動子元素的父盒子的屬性值,觸發BFC,以此來包含子元素的浮動盒子。

使用BFC包含浮動元素

注意,這裏觸發BFC並不能阻止其它形式的脫離文檔流的元素覆蓋正常流元素。

BFC內部其餘形式脫離文檔流(absolute fixed)

5.3 阻止由於瀏覽器由於四捨五入形成的多列布局換行的狀況

有時候由於多列布局採用小數點位的width致使由於瀏覽器由於四捨五入形成的換行的狀況,能夠在最後一列觸發BFC的形式來阻止換行的發生。好比下面栗子的特殊狀況

使用BFC阻止多列布局最後一列換行

5.4 阻止相鄰元素的margin合併

屬於同一個BFC的兩個相鄰塊級子元素的上下margin會發生重疊,(設置writing-mode:tb-rl時,水平margin會發生重疊)。因此當兩個相鄰塊級子元素分屬於不一樣的BFC時能夠阻止margin重疊。 這裏給任一個相鄰塊級盒子的外面包一個div,經過改變此div的屬性使兩個原盒子分屬於兩個不一樣的BFC,以此來阻止margin重疊。

使用BFC阻止margin合併

可是這裏有個疑問: 若是外面包一層div,設置能觸發BFC的任何屬性都能阻止相鄰元素的margin合併。由於分屬不一樣BFC不會發生margin合併。 而若是在外面不包一個div的話,當設置display爲inline-block、inline-flex、table-captain,和position爲absolute、fixed,float爲left、right是能夠阻止margin合併的。這裏問題來了:

咱們知道設置position和float會讓元素脫離文檔流而且又建立新的BFC,因此兩個元素就不是相鄰元素了,所以能夠阻止相鄰元素margin合併,可是inline-block、inline-flex、inline-grid、table-captain爲何能夠呢?若是有人知道爲何,請告知~


網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~

參考:

  1. 我對BFC的理解
  2. 深刻理解BFC和Margin Collapse
  3. 深刻理解BFC
  4. Understanding Block Formatting Contexts in CSS
  5. 學習BFC
  6. Understanding Block Formatting Contexts in CSS
  7. 帶你完全掌握 CSS 浮動

PS:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~

另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~

相關文章
相關標籤/搜索