淺談BFC

BFC是什么?為啥要知道這個東西?今天我們來搞搞清楚。

首先,我們得弄清楚“視覺格式化模型”(visual formatting model)這個東西。要弄清楚這個,我們得先說說瀏覽器的渲染原理了。

http://taligarsiel.com/Projects/howbrowserswork1.htm

這是我很喜歡的一篇闡述瀏覽器運行原理的說明類文章,其中有一章提到了CSS的視覺模型(visual model)。根據其中的講述,瀏覽器是在畫板中繪制“格式化文檔結構”的,而在繪制的過程中,瀏覽器會為每一個元素節點都創建一個矩形空間并在其中放置文檔樹的內容,這也就是大名鼎鼎的css盒模型,而其放置元素的依據就是視覺格式化模型。

話說,這些被創建的盒子都有一個叫做display的屬性,來表明它到底是啥樣的盒子。也就是說,根據display的值,元素會對應不同類型的controlling box。而針對不同類型的盒子,視覺格式化模型會反饋出不同的顯示機制。盒子的類型大概有:

塊盒(block box):

當一個盒子的display屬性被設置為block,list-item或 table時,會生成block-level box

行內盒(inline box):

當一個盒子的display屬性被設置為inline,inline-block或 inline-table,會生成inline-level box

匿名盒(anonymous box):

不能利用選擇器來選擇的盒子,所以它們的屬性為:inherit或默認初始值

那么如上所述,BFC指的就是所謂的“塊盒”所參與到的塊級格式化過程中。同理可以類推,行內盒參與到的則是行內格式化上下文的過程,成為IFC。要注意,只有block-level box才能參與到BFC的過程中,是只有哦。同樣,IFC也是同樣的道理。

關于FC,再多說兩句。每個盒子都有且僅有一個FC值,簡單理解,不同的FC值代表一組盒子不同的排列方式。BFC值表示盒子從上到下垂直排列,而IFC則是表示盒子從左到右的水平排列方式。inline-level box的FC特性值固定為IFC。

每個BFC都有自己獨特的作用域范圍,并不互相影響。可以把它理解為一個容器,元素在其中按照自己的規則進行排列展示,但其他的BFC卻不感知。

如此,相信大家已經理解了BFC產生的原因了。那么,到底哪些條件會觸發BFC呢?整理一下從各方搜集來的資料:

  • body根元素或其它包含它的元素;
  • 浮動 (元素的float不為none,脫離文檔流);
  • 絕對定位元素 (元素的position為absolute或fixed,脫離文檔流);
  • 行內塊 inline-blocks(元素的 display: inline-block,具有block的特征);
  • 表格單元格(元素的display: table-cell,HTML表格單元格默認屬性);
  • overflow的值不為visible的元素 (hidden、auto、scroll);
  • 彈性盒 flex boxes (元素的display: flex或inline-flex);

從這里可以看出,凡事具有塊級元素特征的盒子,或者是脫離文檔流的元素都屬于BFC,同時,我們熟悉的overflow屬性也可以創建BFC。

BFC具有自己獨特的布局規則。也整理一下:

  • 內部的盒子會在垂直方向一個個地放置
  • 屬于同一個BFC的兩個相鄰Box的上下margin會發生重疊,與方向無關
  • 每個元素的左邊,與包含的盒子的左邊相接觸(對于從左往右的格式化,否則相反),即使存在浮動也是如此
  • BFC的區域不會與float的元素區域重疊
  • BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面元素,反之亦然
  • 計算BFC的高度時,浮動元素也參與計算

好了,概念性的東西到此為止。到目前為止,我們理解了BFC是如何形成的、如何觸發的以及如何布局的,那么當遇到實際的布局問題的時候,我們同樣也可以根據BFC的原理來對元素布局進行調整,從而達到想要的布局效果。

首先舉一個最常見的相鄰Box上下margin重疊的例子吧:

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

</style>

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

我們可以分析一下上面的這個簡單例子。首先,body根元素觸發了BFC,所以其中包含的兩個元素P屬于該BFC下的相鄰Box,這時候對其賦值margin屬性,會命中相應的布局規則。因此,最終的布局效果是這樣的:

那么,如果要改進這種布局的話,只需要讓兩個div從屬于不同的BFC即可。實現的方式比較多:

方法一:

<div class="p"></div>  
<div class="wrap">  
    <div class="p"></div>  
</div>  
.warp{
  overflow: hidden;
}
.p{……}

方法二:

<div class="p1"></div>  
<div class="p2"></div>  
.p2{
    float: left;
}

方法三:

<div class="p1"></div>  
<div class="p2"></div>  
.p2{
    display: inline-block;
}

其實,本質上都是一樣的,給body的子元素創建一個BFC,從而避免margin的折疊。

再舉一個清除浮動覆蓋的例子。

<div>
    <div class="aside"></div>
    <div class="main"></div>
</div>    
.aside {
  width: 100px;
  height: 150px;
  float: left;
  background: #f66;
}

.main {
  height: 200px;
  width: 200px;
  background: #fcc;
}

上述代碼會導致浮動內容對主內容的覆蓋。

所以,如果對BFC有了了解,我們就可以得知,產生覆蓋的原因是,浮動的內容創建了新的BFC,導致其左邊與包含的盒子的左邊重合,從而導致了內容覆蓋。因此,清除覆蓋的辦法也很簡單,對其覆蓋元素創建另外的BFC就可以避免這個現象。

<div>
    <div class="aside"></div>
    <div class="main"></div>
</div>    
.aside {
  width: 100px;
  height: 150px;
  float: left;
  background: #f66;
}

.main {
…… 
overflow: hidden; //其他任何觸發BFC的條件都可以
}

效果如下:

那么,為什么創建為新的BFC的main沒有也貼到包含盒子的左邊呢?當然是因為BFC區域不與浮動元素相重疊啦~

最后一個簡單的例子,利用BFC清除浮動

<div class="parent”>

    overflow:hidden;

        <div class="child"></div>

        <div class="child"></div>

</div>

    .parent {

        border: 5px solid #fcc;

        width: 300px;

    }

    .child {

        border: 5px solid #f66;

        width:100px;

        height: 100px;

        float: left;

    }

如此,表象為:

所以,如果想讓內容把這個區域撐開,我們可以通過在parent元素上設置BFC來實現。

.parent {

    overflow: hidden; //其他可以創建BFC的屬性均可

 }

在這個例子中,值得注意的是,DOM中存在一個匿名盒子“overflow:hidden;”,而這個盒子的display屬性會繼承父元素的該屬性,所以,對parent元素的不同的BFC設置會影響到該行文字的顯示位置。比如:

.parent {
    display: flex; 
 }

好了,就說這么多。有空我們再說說IFC,甚至是GFC、FFC吧!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容

  • 什么是BFC? BFC(Blcok Formatting Context) 塊級格式化上下文,僅僅概念上理解是不夠...
    泡杯感冒靈閱讀 245評論 0 0
  • 淺談BFC 引入 那是一個寧靜的夜晚,這個夜晚本應如此的完美,代碼加英語,看會直播,睡覺,直到,我遇到了她。她令我...
    不曾忽然七日閱讀 235評論 0 0
  • relative:生成相對定位的元素,通過top,bottom,left,right的位置相對于其正常位置進行定位...
    zx9426閱讀 954評論 0 2
  • 常見的布局方案 在講 BFC 之前,我們先來了解一下常見的布局方案,有三種常見方案: 普通流 (normal fl...
    饑人谷_zhangfan閱讀 286評論 0 0
  • BFC box,Formatting Context在解釋 BFC 是什么之前,需要先介紹 Box、Formatt...
    詹亮的小倉庫閱讀 297評論 0 7