BFC——一個我們容易忽視掉的布局神器
今天給大家說說BFC這個概念,在說概念前,先給大家看個例子:
首先,定義三個div塊元素
效果:
我們發現,塊級元素的排列順序是從上往下,一塊接着一塊,在w3c中,是這樣解釋block-level box的:
在一個塊級排版上下文中,盒子是從包含塊頂部開始,垂直的一個接一個的排列的。
相鄰兩個盒子之間的垂直的間距是被margin屬性所決定的,在一個塊級排版上下文中相鄰的兩個塊級盒之間的垂直margin是折疊的
咱們看個例子:
代碼如下:
在圖中我們發現,在給兩個塊級元素設置同樣的margin-bottom值時,他們之間會發生margin折疊
觀察此圖,你會發現 class為 d1的塊元素的margin已經與 d2塊元素的margin產生折疊
在d2與d3中,也發生折疊現象,d3margin-top設置為60px,d2margin-bottom設置為50px,所以多了10px
好了,既然我們發現這種折疊的現象,我們就思考,怎么解決這種問題?
好,今天的主角登場:BFC
一、BFC概念:
Block Formatting Contexts 即塊級格式化上下文,其中 Formatting Context 是一個決定如何渲染文檔的容器
Formatting context是W3C CSS2.1規范中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。
最常見的Formatting context有Block fomatting context(BFC)和Inline formatting context(IFC)。CSS2.1 中只有BFC和IFC, CSS3中還增加了GFC和FFC。
上面是來自w3c的對於BFC的概念,下面說說具體:
創建的BFC元素就是一個獨立的盒子(見右下方圖),只有Blcok-level box(塊級盒) 可以創建BFC,它規定了內部的Block-level Box如何布局,並且與這個獨立盒子里的布局不受外部影響,當然它也不會影響到外面的元素。圖中margin、border、padding、content分別定義了元素四種邊,然后每種類型的邊的四條邊定義了一個盒子,分別是content box、padding box、border box、margin box,而決定塊盒在包含塊中與相鄰塊盒的垂直間距的便是margin-box,這個margin-box是始終存在的,即使它的margin為0
好的,概念咱們說完了,看到這里,是不是有些懵?沒關系,接下來先說說BFC的特性吧:
二、BFC特性:
1.內部的box會在垂直方向,從頂部開始一個接着一個地放置
2.box 垂直方向的距離由margin(外邊距)決定。屬於同一個BFC的兩個相鄰box的margin會發生疊加(例子所提到的盒子margin合並問題)
3.BFC的區域不會與float box疊加
4.BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素,反之亦然
5.計算BFC高度時,浮動元素也參與計算
6.每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。(看應用例子2)
那么我們怎樣才能觸發BFC呢?
三、觸發BFC:
1.設置除 float:none 以外的屬性值(如:left | right)就會觸發BFC
2.設置除 overflow: visible 以外的屬性值(如: hidden | auto | scroll)就會觸發BFC
3.設置 display屬性值為: inline-block | flex | inline-flex | table-cell | table-caption 就會觸發BFC
4.設置 position 屬性值為:absolute | fixed 就會觸發BFC
5.使用 fieldset 元素(可以給表單元素設置環繞邊框的html元素)也會觸發BFC
好了,觸發BFC的方法咱們說完了,那現在咱們來說說BFC有哪些運用吧:
四、應用BFC:
1.解決margin疊加問題
這里給出例子:
我們給例子中d1設置一個display:inline-block屬性
效果:
此時,由於d1塊元素通過display:inline-block觸發了BFC,使得margin折疊得以解決,所以,此時的d1的margin-bottom,與d2的margin-top就不會發生折疊了。
2.用於布局
這里給出一個有缺陷的自適應兩欄布局的例子:
先給出代碼:
我們給d1設置了float: left 屬性,則d1會觸發BFC,我們看下圖效果:
在圖中我們發現由於d1觸發BFC,d2將d1包含,即d2元素的margin-box的左邊, 與包含塊d1的border box的左邊相接觸(符合從左向右的格式化)。即使存在浮動float:left也是如此。
那么,並沒有達到我們想要的兩欄布局需求(在d1下多了d2的一部分),那現在我們怎么解決這個問題?
先上代碼:
這里我們給d2元素設置了overflow屬性,讓其也觸發BFC,這樣,將d1與d2變成了兩個相互隔離的獨立盒子,此時這兩個獨立盒子里的布局不受外部影響,也不會影響到外面的元素
我們看效果:
此時這個效果就是我們想要的兩欄布局效果了,這就是利用了BFC進行布局的一個實例,記住!觸發BFC的元素會變成一個獨立的盒子,這個獨立盒子里的布局不受外部影響,也不會影響到外面的元素!這就是BFC的精髓所在!
3.用於清除浮動,計算BFC高度
BFC還可以用於清除浮動,具體先上代碼:
效果:
在這里我們給父元素設置了一個border,我們想讓父元素包裹住d1,可是當d1設置float屬性后(即觸發BFC),我們發現,父元素無法包裹d1了
那么,我們該怎么清除由float觸發BFC帶來的問題呢?
我們知道,在計算BFC
的高度時,浮動元素也參與計算,現在子元素d1已經觸發BFC(即成為獨立盒子),那么父元素是不是也可以通過觸發BFC,在計算高度時可以讓
子元素d1也實現浮動元素的高度計算呢?
我們來試試:
我們給父元素設置overflow:auto 屬性來觸發BFC
效果:
果然,給父元素設置BFC,確實可以讓d1這個浮動元素隨父元素進行高度計算,這樣,我們就解決了利用BFC清除浮動的問題。
總結:今天給大家總結的BFC的一些概念及應用,希望大家可以好好理解。遠方還有許多坑。