CSS-BFC

BFC

  1. box,Formatting Context

    在解釋 BFC 是什么之前,需要先介紹 Box、Formatting Context的概念。

  2. Box: CSS布局的基本單位

    Box 是 CSS 布局的對象和基本單位, 直觀點來說,就是一個頁面是由很多個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),因此Box內的元素會以不同的方式渲染。讓我們看看有哪些盒子:

    • block-level box:display 屬性為 block, list-item, table 的元素,會生成 block-level box。并且參與 block fomatting context;
    • inline-level box:display 屬性為 inline, inline-block, inline-table 的元素,會生成 inline-level box。并且參與 inline formatting context;
    • run-in box: css3 中才有, 這兒先不講了。
  3. Formatting context

    Formatting context 是 W3C CSS2.1 規范中的一個概念。它是頁面中的一塊渲染區域,并且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。最常見的 Formatting context 有 Block fomatting context (簡稱BFC)和 Inline formatting context (簡稱IFC)。

    CSS2.1 中只有 BFC 和 IFC, CSS3 中還增加了 GFC 和 FFC。

  4. 什么是BFC
    在一個Web頁面的CSS渲染中,塊級格式化上下文 (Block Fromatting Context)是按照塊級盒子布局的。W3C對BFC的定義如下:

    浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子,都會為他們的內容創建新的BFC(塊級格式上下文)。
    為了便于理解,我們換一種方式來重新定義BFC。一個HTML元素要創建BFC,則滿足下列的任意一個或多個條件即可:

    1、float的值不是none。

    2、position的值不是static或者relative。

    3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex

    4、overflow的值不是visible

    BFC是一個獨立的布局環境,其中的元素布局是不受外界的影響,并且在一個BFC中,塊盒與行盒(行盒由一行中所有的內聯元素所組成)都會垂直的沿著其父元素的邊框排列。

    IFC布局規則:

    IFC(Inline Formatting Contexts)直譯為"內聯格式化上下文",IFC的line box(線框)高度由其包含行內元素中最高的實際高度計算而來(不受到豎直方向的padding/margin影響)IFC中的line box一般左右都貼緊整個IFC,但是會因為float元素而擾亂。float元素會位于IFC與與line box之間,使得line box寬度縮短。 同個ifc下的多個line box高度會不同。 IFC中時不可能有塊級元素的,當插入塊級元素時(如p中插入div)會產生兩個匿名塊與div分隔開,即產生兩個IFC,每個IFC對外表現為塊級元素,與div垂直排列。
    在行內格式化上下文中,框(boxes)一個接一個地水平排列,起點是包含塊的頂部。水平方向上的 margin,border 和 padding在框之間得到保留。框在垂直方向上可以以不同的方式對齊:它們的頂部或底部對齊,或根據其中文字的基線對齊。包含那些框的長方形區域,會形成一行,叫做行框。

    那么IFC一般有什么用呢?

    水平居中:當一個塊要在環境中水平居中時,設置其為inline-block則會在外層產生IFC,通過text-align則可以使其水平居中。

    垂直居中:創建一個IFC,用其中一個元素撐開父元素的高度,然后設置其vertical-align:middle,其他行內元素則可以在此父元素下垂直居中。

      .container{
         background: grey;
         text-align: center;
         height: 400px;
         width: 800px;
         display: table-cell;
         vertical-align: middle;
    
    
     }
    
     .column {
         width: 200px;
         height: 50px;
         background-color: green;
         display: inline-block;
         
     }
    

    BFC布局規則:

    1. 內部的Box會在垂直方向,一個接一個地放置。
    2. Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發生重疊
    3. 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
    4. BFC的區域不會與float box重疊。
    5. BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
    6. 計算BFC的高度時,浮動元素也參與計算
  5. 怎么創建BFC

    要顯示的創建一個BFC是非常簡單的,只要滿足上述4個CSS條件之一就行。例如:

     <div class="container">
       你的內容
     </div>
    

    在類container中添加類似 overflow: scroll,overflow: hidden,display: flex,float: left,或 display: table 的規則來顯示創建BFC。雖然添加上述的任意一條都能創建BFC,但會有一些副作用:

    1、display: table 可能引發響應性問題
    2、overflow: scroll 可能產生多余的滾動條
    3、float: left 將把元素移至左側,并被其他元素環繞
    4、overflow: hidden 將裁切溢出元素

    因而無論什么時候需要創建BFC,都要基于自身的需要來考慮。對于本文,將采用 overflow: hidden 方式:

     .container {
         overflow: hidden;
     }
    
  6. BFC可以做什么呢?

    1. 利用BFC避免外邊距折疊

      BFC可能造成外邊距折疊,也可以利用它來避免這種情況。BFC產生外邊距折疊要滿足一個條件:兩個相鄰元素要處于同一個BFC中。所以,若兩個相鄰元素在不同的BFC中,就能避免外邊距折疊。

       <head>
           <meta charset="UTF-8">
           <title>bfc</title>
           <style>
               body,ul,p,li{
                   margin: 0;
                   padding: 0;
               }
               .container{
                   width: 800px;
                   height: 700px;
                   background: grey;
                   float: left;
               }
       
               .container p{
                   width: 200px;
                   height: 100px;
                   margin: 50px;
                   background: yellow;
               }
       
               .p3_container{
                   overflow: hidden;
               }
           </style>
       </head>
       <body>
           <div class="container">
               <p>p1</p>
               <p>p2</p>
               <div class="p3_container">
                   <p>p3</p>
               </div>
           </div>
       </body>
      
    2. BFC包含浮動(解決高度塌陷)(計算BFC的高度時,浮動元素也參與計算)
      浮動元素是會脫離文檔流的(絕對定位元素會脫離文檔流)。如果一個沒有高度或者height是auto的容器的子元素是浮動元素,則該容器的高度是不會被撐開的。我們通常會利用偽元素(:after或者:before)來解決這個問題。BFC能包含浮動,也能解決容器高度不會被撐開的問題。

    3. 使用BFC避免文字環繞(BFC的區域不會與float box重疊)

      對于浮動元素,可能會造成文字環繞的情況(Figure1),但這并不是我們想要的布局(Figure2才是想要的)。要解決這個問題,我們可以用外邊距,但也可以用BFC。

        .container{
           width: 800px;
           height: 700px;
           background: grey;
           float: left;
       }
       <div class="container">
      
           <div class="img-container"><img src="../images/square-02.png" alt=""></div>
           <p>        First let us understand why the text wraps. For this we have to understand how the box model
               works when an element is floated. This is the part I left earlier while discussing
               the alignment in a block formatting context. Let us understand what is happening in
               Figure 1 in the diagram below:
           </p>
       </div>
      

      造成文字環繞的原因

      在BFC上下文中,每個盒子的左外側緊貼包含塊的左側(從右到左的格式里,則為盒子右外側緊貼包含塊右側),甚至有浮動也是如此(盡管盒子里的行盒子 Line Box 可能由于浮動而變窄),除非盒子創建了一個新的BFC(在這種情況下盒子本身可能由于浮動而變窄)。
      因而,如果p元素創建一個新的BFC那它就不會再緊貼包含塊的左側了。

    4. 在多列布局中使用BFC

      如果我們創建一個占滿整個容器寬度的多列布局,在某些瀏覽器中最后一列有時候會掉到下一行。這可能是因為瀏覽器四舍五入了列寬從而所有列的總寬度會超出容器。但如果我們在多列布局中的最后一列里創建一個新的BFC,它將總是占據其他列先占位完畢后剩下的空間。

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

推薦閱讀更多精彩內容