我們常用,卻容易忽視——CSS的BFC(Block formatting contexts)


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的一些概念及應用,希望大家可以好好理解。遠方還有許多坑。


免責聲明!

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



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