BFC的我的理解

一直記得我公司的技術Leader對我說的一句話: 
當咱們學習同樣知識的時候,咱們能夠經過「3W+H」(what,when,why,how)的方法來檢驗本身對該知識點的掌握程度,若是你對上述的「3W」都能十分清楚的回答上來,說明你對該知識點的掌握還能夠,若是不能,則說明你根本就沒掌握

下面就BFC用「3W」的方法,談一下本身對它的我的看法:css

What:什麼是BFC

MDN官方說法:html

塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其餘元素交互的區域。

視覺格式化模型(visual formatting model)bash

是用來處理文檔並將它顯示在視覺媒體上的機制(說白了,這個模型就是控制生成不一樣的盒子),視覺格式化模型定義了盒(Box)的生成,盒主要包括了塊盒、行內盒、匿名盒(沒有名字不能被選擇器選中的盒)以及一些實驗性的盒(將來可能添加到規範中)。盒的類型由display屬性決定。佈局

學過CSS的都知道,頁面上的元素基本上都是一個個的盒子組成的(包括塊盒、行內盒、匿名盒(沒有名字不能被選擇器選中的盒)),下面咱們先來溫習一下幾個重要的盒子:post

塊盒(block box)

塊盒有如下特性:學習

  • 當元素的CSS屬性displayblocklist-itemtable時,它是塊級元素 block-level;
  • 視覺上呈現爲塊,豎直排列;
  • 塊級盒參與(塊格式化上下文);
  • 每一個塊級元素至少生成一個塊級盒,稱爲主要塊級盒(principal block-level box)。一些元素,好比<li>,生成額外的盒來放置項目符號,不過多數元素只生成一個主要塊級盒。

行內盒(inline box)

  • 當元素的CSS屬性display的計算值爲inlineinline-blockinline-table時,稱它爲行內級元素;
  • 視覺上它將內容與其它行內級元素排列爲多行;典型的如段落內容,有文本(能夠有多種格式譬如着重),或圖片,都是行內級元素;
  • 行內級元素生成行內級盒(inline-level boxes),參與行內格式化上下文(inline formatting context)。同時參與生成行內格式化上下文的行內級盒稱爲行內盒(inline boxes)。全部display:inline的非替換元素生成的盒是行內盒;
  • 不參與生成行內格式化上下文的行內級盒稱爲原子行內級盒(atomic inline-level boxes)。這些盒由可替換行內元素,或 display 值爲 inline-blockinline-table 的元素生成,不能拆分紅多個盒;

匿名盒(anonymous box)

匿名盒也有份匿名塊盒與匿名行內盒,由於匿名盒沒有名字,不能利用選擇器來選擇它們,因此它們的全部屬性都爲inherit或初始默認值;flex

塊盒和行內盒咱們你們都比較熟悉了,下面舉個簡單的例子說明一下匿名盒:ui

<div class="container"> 
       我是小妖怪,逍遙又自在 
       <h1>殺人不見血</h1>
       吃人不放鹽  
</div>複製代碼

什麼樣式也沒加,其中. container就是一個默認的塊元素,可是「我是小妖怪」也會生成一個盒子,因爲咱們沒法用css選擇器來選擇它,因此這個盒子也就是匿名盒子。

總而言之:BFC是決定塊盒子的佈局以及浮動相互影響的區域,歸根揭底,BFC就是在CSS渲染的時候造成的一個塊級區域,關於這個區域的特色,請見下文。atom

HOW:怎樣造成一個BFC

  • 根元素(html)或其它包含它的元素;
  • 浮動 (元素的float不爲none);
  • 絕對定位元素 (元素的positionabsolutefixed);
  • 行內塊inline-blocks(元素的 display: inline-block);
  • 表格單元格(元素的display: table-cell,HTML表格單元格默認屬性);
  • overflow的值不爲visible的元素;
  • 彈性盒 flex boxes (元素的display: flexinline-flex);

也就是說,知足上面的任何一個條件,就會造成一個BFC,其中最多見的就是overflow:hiddenfloat:left/rightposition:absolute。spa


BFC的範圍

BFC包含建立該上下文元素的全部子元素,但不包括建立了新BFC的子元素的內部元素。

也就是說,一個BFC包含包含建立該上下文元素的全部子元素,但若是在一個BFC裏面又生成了新的BFC,那麼內部BFC的子元素將不受外部BFC的影響。也就是說對於一個具體的元素而言,其只能屬於一個BFC,而不能同屬於多個BFC。


BFC的特性:

  • 內部的盒會在垂直方向一個接一個排列(能夠看做BFC中有一個的常規流);
  • 處於同一個BFC中的元素相互影響,可能會發生margin collapse(垂直方向margin重疊);
  • 每一個元素的margin box的左邊,與容器塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此;
  • BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然(外部的元素也不會影響容器內部的子元素);
  • 計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算(不會發生高度塌陷);
  • 浮動盒區域不疊加到BFC上(也就是說,浮動的元素不會遮擋住BFC);

  • 下面就以上的幾個特性用例子實際說明一下:

    1. 內部的盒會在垂直方向一個接一個排列(能夠看做BFC中有一個的常規流);

    <style> 
          .bfc{
                position: absolute; //使用了絕對定位,造成一個BFC
                left: 100px;
                top:100px;
                width: 200px;
                height: 200px;
                border: 1px solid #ffcccc;
                background:rgba(220, 14, 129, 0.5)
            }        
        .item1,.item2{
            border: 1px solid green; 
            padding: 10px;
            margin: 20px
          }    
    </style>複製代碼

    <div class="container bfc"  >
            <div class="item1">2</div>
            <div class="item2">3</div>
    </div>複製代碼

    其結果就是這樣子:


    可見在BFC內部造成正常的文檔流,但卻發生了方向上的margin重疊,要解決這個重疊,能夠在內部從新生成一個新的BFC:

    <div class="container bfc"  >
            <div class="item1">2</div>
            <div class="bfc-inner">
                <div class="item2">3</div> 
           </div>
     </div>複製代碼

    <style>
        .bfc{ 
            position: absolute;
            left: 100px;
            top:100px;
            width: 200px;
            height: 200px;
            border: 1px solid #ffcccc; 
            background:rgba(220, 14, 129, 0.5)
        }
        .item1,.item2{
            border: 1px solid green; 
            padding: 10px;
            margin: 20px;
         }        
        .bfc-inner{
            float: left ;// 新的bfc 
         }        
        .bfc-inner .item2{ 
           width: 100% 
         }
    </style>複製代碼


    margin的重疊不見了,由於item2已經不屬於外部的BFC了

    2. 計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算(不會發生高度塌陷);

    <style>
        .bfc{
            border: 1px solid #000;
         }        
        .item1,.item2{
                border: 1px solid green;
                width: 100px; 
                height: 100px;
                float: left
         }        
        .item1{            
            background:blueviolet;
            opacity: 0.4;
         }        
        .item2{
            background:brown;
            opacity: 0.4;
        }    
    </style>複製代碼

    <div class="bfc"  >
        <div class="item1">2</div>
        <div class="item2">3</div>
     </div>複製代碼

    會發生典型的高度塌陷:


    可是當咱們給.bfc元素添加樣式position:absolute或者float:left的時候,就會造成一個BFC,高度塌陷就消失了。



    3.  浮動盒區域不疊加到BFC上(也就是說,浮動的元素不會遮擋住BFC);

    仍是使用上面的元素,不過樣式變成了這個樣子:

    <style>        
        .bfc{
             border: 1px solid #000;
           }        
        .item1,.item2{
               border: 1px solid green; 
        }        
        .item1{
                background:blueviolet;
                width: 100px;
                height: 100px;
                float: left
         }        
        .item2{
             width: 300px;
             height: 100px;
             background:brown;
         }
    </style>複製代碼

    這樣的話,.item2就會被.item1遮擋


    可是當咱們給.item2添加一個樣式:overflow:hidden的時候(造成了一個BFC),就不會被遮擋了。


    WHEN和WHY

    對於BFC,在我看來更像是一個策略,可使用BFC的特性來解決不一樣的佈局問題,好比高度塌陷,好比浮動遮擋的問題,垂直方向margin摺疊等,其實咱們會發現咱們無心間就會使用BFC,理解並靈活使用BFC能讓咱們在佈局的時候避免不少坑。

    參考文章:

    juejin.im/post/59b73d…(網易考拉:學習BFC)

    相關文章
    相關標籤/搜索