深入理解 BFC

A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with other elements.

什麼是 BFC

BFC 全稱是 block formatting context,翻譯成中文就是塊級格式化上下文。在很多 CSS 教程中,很少有直接提到 BFC 的。那這是不是說明 BFC 不重要呢?其實不是的,BFC 在有些地方有着很大的作用。

BFC 的特點

Block formatting contexts are important for the positioning (see float) and clearing (see clear) of floats.The rules for positioning and clearing of floats apply only to things within the same block formatting context.

BFC 主要特點:

  • Floats do not affect the layout of the content inside other block formatting contexts, and clear only clears past floats in the same block formatting context.
  • Margin collapsing also occurs only between blocks that belong to the same block formatting context.

如何創建 BFC

A block formatting context is created by at least one of the following:

  • the root element or something that contains it
  • floats (elements where float is not none)
  • absolutely positioned elements (elements where position is absolute or fixed)
  • inline-blocks (elements with display: inline-block)
  • table cells (elements with display: table-cell, which is the default for HTML table cells)
  • table captions (elements with display: table-caption, which is the default for HTML table captions)
  • anonymous table cells implicitly created by the elements with display: table, table-row, table-row-group, table-header-group, table-footer-group (which is the default for HTML tables, table rows, table bodies, table headers and table footers, respectively), or inline-table
  • block elements where overflow has a value other than visible
  • display: flow-root
  • elements with contain: layout, content, or strict
  • flex items (direct children of the element with display: flex or inline-flex)
  • grid items (direct children of the element with display: grid or inline-grid)
  • multicol containers (elements where column-count or column-width is not auto, including elements with column-count: 1)

上面基本上列出了創建 BFC 的全部方式,但是我們不可能也不必要每種方式都記住。

我們常用的主要有以下方式:

  • overflow 不爲 visible
  • position 設置爲絕對定位(包括 absolute 和 fixed)
  • float 不爲 none
  • display 設置爲 inline-block、table-cell、table-caption、flex 等

BFC 應用場景

清除浮動

<body>
    <h1>清除浮動</h1>
    <div class="container">
        <div class="left">左側欄: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
        proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
        <div class="right">右側欄:Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
        proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
    </div>
    <div class="footer">
        <p>底部底部底部底部底部底部底部底部底部</p>
    </div>
</body>
h1 {
    margin: 10px 0;
    text-align: center;
}
.left {
    width: 400px;
    float: left;
    background-color: #f00;
}
.right {
    width: 400px;
    float: left;
    background-color: #0f0;
}

這裏寫圖片描述

如圖所示,由於內容元素設置了 float 屬性,導致底部的元素沒有另起一行渲染,而是直接跟在了第二個內部元素的後面。當我們爲父元素設置 BFC 後,就能解決這個問題。

h1 {
    margin: 10px 0;
    text-align: center;
}
.container {
    overflow: hidden;     // 設置 BFC
}
.left {
    width: 400px;
    float: left;
    background-color: #f00;
}
.right {
    width: 400px;
    float: left;
    background-color: #0f0;
}

這裏寫圖片描述

只要設置 BFC 就能清除浮動了。不過這樣清除浮動會有副作用,所以一般全局的清除浮動樣式不會這樣寫,不過在某些地方還是可以直接使用的。有興趣看一看 bootstrap 的全局清除浮動樣式,戳這裏查看

防止外邊距重疊

外邊距重疊有兩種現象,不過都可以使用 BFC 來解決。

子元素與子元素

<h1>子元素與子元素</h1>
<div class="container">
    <div class="top">大明: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
    <div class="bottom">小明:Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
h1 {
    margin: 10px 0;
    text-align: center;
}
.top {
    margin-bottom: 100px;
    background-color: #f00;
}
.bottom {
    margin-top: 50px;
    background-color: #0f0;
}

這裏寫圖片描述

這裏給上面的子元素設置了 margin-bottom,給下面的子元素設置了 margin-top,但是最終兩個元素之間的間隔不是 100 + 50 後的 150,而是 100。原因是因爲發生了 margin collapsing,這不是一個 bug,而是 w3c 的一個規定。但是有時候我們並不需要這個特性,那如何解決呢?

其中一個方法就是利用 BFC,給第二個元素設置 position 的值爲 absolute/fixed 或 float:left。

h1 {
    margin: 10px 0;
    text-align: center;
}
.top {
    margin-bottom: 100px;
    background-color: #f00;
}
.bottom {
    margin-top: 50px;
    position: absolute;     // 設置 BFC
    background-color: #0f0;
}

這裏寫圖片描述
子元素與父元素

<div class="container">
    <div class="box">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
h1 {
    margin: 10px 0;
    text-align: center;
}
.container {
    height: 300px;
    background-color: #0f0;
}
.box {
    margin-top: 100px;
    background-color: #f00;
}

這裏寫圖片描述

這裏將子元素的 margin-top 設置爲了 100px,但現象是父元素的生效了,並我們預想的子元素距父元素的上邊 100px。這裏也是發生了 margin collapsing 外邊距塌陷。

解決方法之一和上面一樣,利用 BFC。我們只需要給父元素加一個 overflow: hidden; 即可。

h1 {
    margin: 10px 0;
    text-align: center;
}
.container {
    height: 300px;
    overflow: hidden;       // 設置 BFC
    background-color: #0f0;
}
.box {
    margin-top: 100px;
    background-color: #f00;
}

這裏寫圖片描述

更多 margin collapsing 戳這裏查看

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章