BFC及其做用

Note:This article is my study note, without copyright,most of the content comes from others.css

1. 爲何出現margin-left塌陷?

推薦:殷榮檜——深度剖析Margin塌陷,BFC,Containing Block之間的關係html

舉個例子,像下面這種狀況,上下兩個盒子的間距按說是20px和40px,但實際都是20px,這就是塌陷。git

<div style="background-color:tomato;width:100px;height:100px;margin-bottom:20px;"> hello world</div>
      <div style="background-color:#bbb;width:100px;height:100px;margin-top:0px;"> hello world</div>
      <hr>
      <div style="background-color:tomato;width:100px;height:100px;margin-bottom:20px;"> hello world</div>
      <div style="background-color:#bbb;width:100px;height:100px;margin-top:20px;"> hello world</div>
複製代碼

其實這是CSS1.0故意設計的,由於這樣符合平面設計師的要求。github

2. 爲何塌陷時只出如今垂直方向?

StackOverflow:爲何塌陷時只出如今垂直方向?瀏覽器

在CSS出現以前使用的p標籤,它要求每一個段落之間有相同的間隔,因此當你對p標籤設置了margin-topmargin-bottom你發現就會出現塌陷的狀況,並且會取兩者之中的最大值。app

明白塌陷產生的條件也就明白瞭如何解決塌陷所帶來的問題,那麼塌陷產生的條件是什麼?less

首先是一個大前提:元素之間沒有被非空內容、padding、border 或 clear 分隔開。而後有符合下面幾種毗鄰狀況:佈局

top margin of a box and top margin of its first in-flow child
(一個元素的 margin-top 和它的第一個子元素的 margin-top)post

bottom margin of box and top margin of its next in-flow following sibling
(普通流中一個元素的 margtin-bottom 和它的緊鄰的兄弟元素的的 margin-top)flex

bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘auto’ computed height
(一個元素( height 爲 auto )的 margin-bottom 和它的最後一個子元素的margin-bottom)

top and bottom margins of a box that does not establish a new block formatting context and that has zero computed ‘min-height’, zero or ‘auto’ computed ‘height’, and no in-flow children
(一個沒有建立 BFC、沒有子元素、height 爲0的元素自身的 margin-top 和 margin-bottom)

這段英文爲摘抄:
原文連接:juejin.im/post/5aebd1…

W3C規範這樣描述:

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
在BFC中,每一個盒子的左外邊框緊挨着包含塊的左邊框(如果從右到左的格式,則爲緊挨右邊框)。即便存在浮動也是這樣的(儘管一個盒子的邊框會因爲浮動而收縮),除非這個盒子的內部建立了一個新的BFC浮動,盒子自己將會變得更窄)。

這段英文爲摘抄:
原文連接:www.w3cplus.com/css/underst… © w3cplus.com

3. 如何解決margin-left塌陷?

方法已在代碼中給出

<div class="wrapper">
         <div class="content">
         </div>
      </div>
複製代碼
* {
         margin: 0;
         padding: 0;
      }

      .wrapper {
         background-color: #000;
         margin-left: 100px;
         margin-top: 100px;
         width: 100px;
         height: 100px;
         /* float: left; */
         /* position: absolute; */
         /* display: inline-block; */
         /* display: flex; */
         /* 注意使用 overflow 溢出的部分會自動隱藏起來*/
         /* overflow: hidden; */
         /* 注意使用display: table雖然能夠解決塌陷,可是cotainer的高度會失效 */
         /* display: table; */
         /* overflow: scroll; */
         /* overflow: scroll 溢出的部分會變成滾動,效果奇葩,應該沒什麼用 */
      }

      .content {
         /* 在子元素中使用如下這些也能夠解決塌陷 */
         /* float: left; */
         /* position: absolute; */
         /* display: inline-block; */
         width: 50px;
         height: 50px;
         background-color: #0f0;
         margin-left: 50px;
         /* 設置 margin-top: 150px;咱們發現子級盒子會帶着父級盒子一塊兒往下移動,好像兩者粘連到了一塊兒或者說子級盒子好像沒有了「頂「。這種現象叫作margin-left塌陷,是經典BUG。 */
         margin-top: 150px;

      }
複製代碼

4. margin合併(也叫margin摺疊)

外邊距摺疊的例子以下

<div class="wrapper"></div>
         <div class="content"></div>
複製代碼
.wrapper{
    height: 20px;
    background-color: #000;
    margin-top: 20px;
    margin-bottom: 200px;
}
.content{
    height: 20px;
    margin-top: 100px;
    background-color: #0f0;
}
複製代碼

解決方法

  1. 使用數學方法(不解決)
  2. 引入BFC;給元素添加父級盒子併爲其父級元素添加屬性overflow: hidden;
  3. BFC可能會致使外邊距摺疊,同時也可使用BFC來解決外邊距摺疊

這一開始聽起來可能有些困惑,由於咱們在前面討論了BFC致使外邊距摺疊的問題。但咱們必須牢記在心的是毗鄰塊盒子的垂直外邊距摺疊只有他們是在同一BFC時纔會發生。若是他們屬於不一樣的BFC,他們之間的外邊距將不會摺疊。因此經過建立一個新的BFC咱們能夠防止外邊距摺疊。 以下,以後給父級元素添加overflow: hidden;便可解決margin合併

<div class="container">
         <div class="content1"></div>
         <div class="content2"></div>
      </div>
      <div class="container">
         <div class="content3"></div>
      </div>
複製代碼

效果以下

上面一段話的原文連接: www.w3cplus.com/css/underst… © w3cplus.com

5. 浮動元素(使用BFC來包含浮動)

浮動元素帶有float的元素,最先用來實現相似於報紙圖片環繞的佈局

<div class="wrapper">
         <div class="content">1</div>
         <div class="content">2</div>
         <div class="content">3</div>
         <div class="content">4</div>
         <div class="content">5</div>
         <div class="content">6</div>
         <div class="content">7</div>
         <div class="content">8</div>
         <div class="content">9</div>
      </div>
      <br>
      <div class="context1">YAMA</div>
      <div class="context2">YAMA</div>
複製代碼
* {
         margin: 0;
         padding: 0;
      }

      .wrapper {
         background-color: aqua;
         /* width: 330px; */
         border: 2px solid black;
         /* 解決方法以下,在父級盒子添加overflow: hidden; */
         overflow: hidden;
      }

      .content {
         float: left;
         /*使元素站隊、浮動*/
         color: #fff;
         margin-left: 10px;
         margin-bottom: 10px;
         background-color: black;
         width: 100px;
         height: 100px;
      }

      .context1 {
         float: left;
         width: 100px;
         height: 100px;
         background-color: red;
         color: white;
         opacity: 0.7;
      }

      .context2 {
         width: 150px;
         height: 150px;
         background-color: yellow;
         color: blue;
         /* 解決方法以下,在後面的元素變爲行內塊 */
         /* display: inline-block; */
         /* float: left; */
         /* float: right; */
      }
複製代碼

效果如圖

此處咱們注意到後面兩個div好像具備層模型的特色,實際上不是,正確理解爲:

浮動元素產生了浮動流,塊級元素看不到全部產生了浮動流的元素 注: 產生了BFC的元素、文本類屬性(帶有inline屬性)的元素以及浮動元素都能看到浮動元素 (這裏所指的看不到指的是在進行定位時會無視它而進行覆蓋,就像層模型同樣絕對定位) (還需注意,若是設置position和float後由內容決定大小,打內部把元素轉換成inline-block)

應用實例

在這裏插入圖片描述

6. 附實例

<div class="wrapper">
         <div class="content">1</div>
         <div class="content">2</div>
         <div class="content">3</div>
         <p>YAMA</p>
      </div>
複製代碼
* {
         margin: 0;
         padding: 0;
      }

      .wrapper {
         border: 10px solid black;
         overflow: hidden;
      }

      .content {
         float: left;
         color: #fff;
         margin: 2px;
         background-color: black;
         width: 100px;
         height: 100px;
      }

      p {
         background-color: cadetblue;
         /* clear: both; */
      }
複製代碼

下圖中上面的圖片設置了overflow: hidden;,下面的沒有

  • p標籤屬於塊級元素會忽視float,在進行定位假設不存在,可是這裏和以前的層模型不同
  • 下面的圖中的下面那部分是p標籤添加clear: both;以後,意義是不容許該標籤附近出現浮動對象,(相應的值還有左右),至關於清除了div標籤的浮動特性。

7. 使用BFC來防止文字環繞

有時候一個浮動div周圍的文字環繞着它(以下圖中的左圖所示)可是在某些案例中這並非可取的,咱們想要的是外觀跟下圖中的右圖同樣的。爲了解決這個問題,咱們可能使用外邊距,可是咱們也可使用一個BFC來解決。

<div class="container">
      <div class="floated">
         <img width="150px" src="https://user-gold-cdn.xitu.io/2020/4/18/1718da4f61a16e59?w=633&h=658&f=png&s=13693">
      </div>
      <p>YAMA YAMA YAMA YAMAYAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMAYAMA YAMA.
         YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMAYAMA YAMA
         YAMA YAMA
         YAMA YAMA YAMA YAMAYAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMAYAMA YAMA.
         YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMA YAMAYAMA YAMA
         YAMA YAMA.</p>
     </div>
複製代碼
.floated {
         float: left;
         margin: 5px;
      }

      p {
         color: rgb(14, 13, 13);
         text-align: center;
         /* 解決方法以下 */
         /* overflow: hidden; */
      }
複製代碼

8. 在多列布局中使用BFC

若是咱們正在建立的一個多列布局佔滿了整個容器的寬度,在某些瀏覽器中最後一列有時候將會被擠到下一行。會發生這樣多是由於瀏覽器舍入(取整)了列的寬度使得總和的寬度超過了容器的寬度。然而,若是咱們在一個列的佈局中創建了一個新的BFC,它將會在前一列填充完以後的後面佔據所剩餘的空間。

<div class="container">
         <div class="column">column 1</div>
         <div class="column">column 2</div>
         <div class="column">column 3</div>
      </div>
複製代碼
.column {
         /* 父元素或者說視窗寬度的31.33%,下面的百分號也是如此 */
         width: 31.33%;
         background-color: green;
         float: left;
         margin: 0 0%;
      }

      .column:last-child {
         float: none;
         overflow: hidden;
      }
複製代碼

如今即便容器的寬度會有輕微的變化,可是佈局也不會中斷。固然,這並非多列布局的最好選擇,但它是防止最後一列下滑問題的一種方法。Flexbox在這種狀況下多是一個更好的解決方案,可是這應該要說明一下在這些狀況下元素是如何表現的。

9. 兩欄佈局

實現兩欄佈局

10. 總結

  1. 根元素(整個頁面就是一個大的BFC);
  2. float爲 left | right;
  3. overflow爲 hidden | auto | scroll;
  4. display爲 inline-block | table-cell | table-caption | flex | inline-flex;
  5. position爲 absolute | fixed;

請注意,BFC並非一個css屬性,也不是一段代碼,而是css中基於box的一個佈局對象,它是頁面中的一塊渲染區域,而且有一套渲染規則,它決定了其子元素將如何定位,以及和其餘元素的關係和相互做用。明確地,它是一個獨立的盒子,而且這個獨立的盒子內部佈局不受外界影響,固然,BFC也不會影響到外面的元素

11. 參考

  1. 深度剖析Margin塌陷,BFC,Containing Block之間的關係
  2. MDN
  3. 理解CSS中BFC
  4. css中的BFC
相關文章
相關標籤/搜索