學習JS原理之BFC

林菜菜發表於2019-12-18

CSS 定位機制

CSS 有三種基本的定位機制:普通流、浮動和絕對定位。

普通流

除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。

塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。

行內框在一行中水平佈置。可以使用水平內邊距、邊框和外邊距調整它們的間距。但是,垂直內邊距、邊框和外邊距不影響行內框的高度。由一行形成的水平框稱為行框(Line Box),行框的高度總是足以容納它包含的所有行內框。不過,設定行高可以增加這個框的高度。

浮動

float 屬性定義元素在哪個方向浮動。浮動元素會生成一個塊級框,而不論它本身是何種元素。

float: left|right|none|inherit;

position定位

任何元素都可以定位,不過絕對或固定元素會生成一個塊級框,而不論該元素本身是什麼型別。相對定位元素會相對於它在正常流中的預設位置偏移。

float: absolute|fixed|relative|static|inherit;

什麼是塊級格式化上下文(BFC)

“BFC即 Block Formatting Contexts (塊級格式化上下文), 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。”

如何觸發BFC

  • body 根元素
  • 浮動元素:float 除 none 以外的值
  • 絕對定位元素:position (absolute、fixed)
  • display 為 inline-block、table-cells、flex、inline-flex、flow-root(沒有副作用的方案,但需注意相容性)、grid、inline-grid等
  • overflow 除了 visible 以外的值 (hidden、auto、scroll)

BFC的特性

1、內部的Box會在垂直方向上一個接一個的放置

2、垂直方向上的距離由margin決定。(完整的說法是:屬於同一個BFC的兩個相鄰Box的margin會發生重疊(塌陷),與方向無關。)

3、每個元素的左外邊距與包含塊的左邊界相接觸(從左向右),即使浮動元素也是如此。(這說明BFC中子元素不會超出他的包含塊,而position為absolute的元素可以超出他的包含塊邊界)

4、BFC的區域不會與float的元素區域重疊

5、計算BFC的高度時,浮動子元素也參與計算

6、BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面元素,反之亦然

BFC的應用

清除浮動(同時說明特性3、特性5、特性6)

<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .child1 {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }
</style>

<body>
  <div class="content-box">
    <div class="child1"></div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

  • 子元素浮動,脫離文件流,父元素高度只剩下border
<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
    overflow: hidden;  // 讓父元素觸發BFC
  }

  .child1 {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }
</style>
複製程式碼

學習JS原理之BFC

  • 觸發父元素的BFC,父元素高度恢復,故計算BFC的高度時,浮動子元素也參與計算(特性5)

防止元素上下margin摺疊(同時說明特性2、特性6)

<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .child {
    width: 200px;
    height: 200px;
    background: #FFA500;
    margin: 50px auto;
  }
</style>

<body>
  <div class="content-box">
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

  • 兩個子元素的上下外邊距發生重疊,距離只差50px(應該為第一個子元素的bottom-margin+第二個元素的top-margin=100px)
<style>
  .content-box {
    background: #fff;
    width: 300px;
    border: 5px solid #FF4500;
  }

  .parent {
    overflow: hidden; // 將外邊距摺疊的元素放入兩個不同的BFC容器中
  }

  .child {
    width: 200px;
    height: 200px;
    background: #FFA500;
    margin: 50px auto;
  }
</style>

<body>
  <div class="content-box">
    <div class="parent">
      <div class="child"></div>
    </div>
    <div class="parent">
      <div class="child"></div>
    </div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

  • 將發生外邊距重疊的子元素分別放入兩個BFC容器中,每個BFC都是一個獨立的容器

實現兩欄佈局

<style>
  .content-box {
    background: #fff;
    width: 300px;
  }

  .left {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }

  .right {
    background: #FF4500;
    color: #fff;
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。

      塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。

      行內框在一行中水平佈置。可以使用水平內邊距、邊框和外邊距調整它們的間距。但是,垂直內邊距、邊框和外邊距不影響行內框的高度。由一行形成的水平框稱為行框(Line
      Box),行框的高度總是足以容納它包含的所有行內框。不過,設定行高可以增加這個框的高度。
    </div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

  • 浮動元素會覆蓋未浮動元素,但文字不會被覆蓋。
<style>
  .content-box {
    background: #fff;
    width: 300px;
  }

  .left {
    width: 200px;
    height: 200px;
    background: #FFA500;
    float: left;
  }

  .right {
    background: #FF4500;
    color: #fff;
    overflow: hidden; // 右側未浮動元素,觸發BFC
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。
      塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。
    </div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

  • 未浮動元素觸發BFC,能避免被浮動元素覆蓋

實現同等高度的兩欄

<style>
  .content-box {
    background: #fff;
    width: 300px;
    overflow: hidden;

  }

  .content-box>div {
    /* 注意這裡 */
    padding-bottom: 100000px;
    margin-bottom: -100000px;
  }

  .left {
    background: #fadc09;
    height: 300px;
    width: 100px;
    float: left;
  }

  .right {
    height: 100px;
    background: #faa509;
    display: flow-root;
  }
</style>

<body>
  <div class="content-box">
    <div class="left"></div>
    <div class="right">
      除非專門指定,否則所有框都在普通流
    </div>
  </div>
</body>
複製程式碼

學習JS原理之BFC

總結

這讓我想起上一次面試的時候,面試題就是讓我實現這樣的兩欄佈局,然而小菜鳥的我,還不是很理解BFC原理竟然用flex,然後寫了好多樣式,而且還及其不智慧。哈哈哈~

以上三種對於BFC的應用都很普遍,再也不用新增新元素,用clear:both來清除浮動拉~

值得一說的是:就在我看了好多BFC相關的文章,學習了BFC相關的原理之後沒幾天,就有同事問我邊距被壓縮的問題,我一看就是邊距重疊了,都沒想就說你拿一個div包一下加個overflow:hidden啥的。瞬間感覺沒有白學呀,感覺自己挺牛逼呀~雖然我知道我其實還是一個小菜鳥。哈哈哈~

但是我會繼續努力噠~

相關文章