1. 程式人生 > >BFC及清除浮動詳解

BFC及清除浮動詳解

一. BFC

BFC 即 Block Formatting Contexts (塊級格式化上下文),具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器裡面的元素不會在佈局上影響到外面的元素,並且 BFC 具有普通容器所沒有的一些特性。通俗一點來講,可以把 BFC 理解為一個封閉的大子,箱子內部的元素無論如何翻江倒海,都不會影響到外部。就像js的函式作用域一樣,BFC是頁面上的作用域。

1.觸發BFC

只要元素滿足下面任一條件即可觸發 BFC 特性:

  1. body 根元素
  2. 浮動元素:float 除 none 以外的值
  3. 絕對定位元素:position (absolute、fixed)
  4. display 為 inline-block、table-cells、flex
  5. overflow 除了 visible 以外的值 (hidden、auto、scroll)

也就是脫離文件流的元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子

2.BFC特性

 (1)同一個 BFC 下外邊距會發生摺疊

<style>
div{
    width: 100px;
    height: 100px;
    background: blue;
    margin: 100px;
}
</style>
<body>
    <div></div>
    <div></div>
</body>

如果我們不瞭解BFC的話,會認為兩個div之間的距離為200px,但其實這兩個div之間的距離只有100px,因為外邊距發生了摺疊,這是css的一種規範。

 (2)BFC 可以包含浮動的元素(清除浮動)

這裡所說的,就是上面方法四和方法五中的原理了,觸發BFC後,容器將會包裹著浮動元素。在方法四五中使用了overflow屬性,也就是我們上面所說的觸發BFC條件中的第五條。

 (3)BFC 可以阻止元素被浮動元素覆蓋

來看下面這個例子:

<div style="height: 100px;
    width: 100px;
    float: left;
    background: blue">
    我是一個左浮動的元素
</div>
<div style="width: 200px; 
    height: 200px;
    background: #eee">
    我是一個沒有設定浮動,也沒有觸發BFC元素
</div>

在這個例子中左浮動的元素會將其他元素覆蓋,但我們並不想其他元素被覆蓋,這時就可以使用BFC,給第二個元素加上overflow:hidden,即可讓第二個元素不再被浮動元素所覆蓋。附BFC詳解地址:https://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.html

二.清除浮動

什麼是浮動?為什麼要清除?浮動就是因為有元素使用了float屬性,使得元素處於半脫離文件流的狀態,無法撐開父元素。來看下面這個例子

<style type="text/css">
.div1{border: 2px solid red}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}
</style>

<body>
<div class="div1">
<div class="left">Left</div>
</div>
<body>

在這個例子中,我們希望它的效果應該是這樣的,父級元素div1應當包含left元素。

但實際效果卻是這樣的

這就是浮動帶來的影響,無法撐開父級元素,父級元素高度為0,這顯然不是我們希望看到的,所以我們要清除浮動。清除浮動共有八種方式,下面來一一介紹,前五種我們可能會使用到,後三種只做瞭解就可以。

1.設定父級元素的高度

這是最簡單容易理解的方式,但只適合高度固定的佈局,要給出精確的高度,如果高度和父級div不一樣時,會產生問題,不推薦使用。

<style type="text/css">
.div1{
    border: 2px solid red;
    height:200px}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}
</style>

2.結尾處加空標籤clear:both

這種方法簡單、程式碼少、瀏覽器支援好、不容易出現怪問題,但原理不好理解,而且如果頁面浮動佈局多,就要增加很多空div,讓人感覺很不好,不推薦使用。關於css的clear屬性大家如果不懂的話可以直接百度,both代表元素的左右都不允許出現浮動元素。

<style type="text/css">
.div1{border: 2px solid red}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}

.clearfloat{clear:both}
</style>

<body>
<div class="div1">
<div class="left">Left</div>

<div class="clearfloat"></div>
</div>
<body>

3.父級div定義 偽類:after 和 zoom

原理類似方法2,瀏覽器支援好、不容易出現怪問題,大部分的網站都在用,建議使用,但程式碼多、不少初學者不理解原理,要兩句程式碼結合使用才能讓主流瀏覽器都支援。其中的{zoom:1}是相容IE6/7的寫法,IE6/7通過zoom:1可以觸發hasLayout。

<style type="text/css">
.div1{border: 2px solid red}
.left{float:left;
    width:20%;
    height:200px;
    background:#DDD}
.clearfloat:after{
    display:block;
    clear:both;
    content:"";
    display:hidden;
    height:0}
.clearfloat{zoom:1}
</style>
<body>
<div class="div1 clearfloat">
<div class="left">Left</div>
</div>
<body>

4. 父級div定義 overflow:hidden

簡單、程式碼少、瀏覽器支援好,不能和position配合使用,因為超出的尺寸的會被隱藏。只推薦沒有使用position或對overflow:hidden理解比較深的朋友使用。這個方法與第五個方法的原理都是觸發了BFC。

<style type="text/css">
.div1{
    border: 2px solid red;
    overflow:hidden}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}
</style>

<body>
<div class="div1">
<div class="left">Left</div>
</div>
<body>

5.父級div定義 overflow:auto

簡單、程式碼少、瀏覽器支援好,但內部寬高超過父級div時,會出現滾動條。不推薦使用,如果你需要出現滾動條或者確保你的程式碼不會出現滾動條就使用吧。

<style type="text/css">
.div1{
    border: 2px solid red;
    overflow:auto}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}
</style>

<body>
<div class="div1">
<div class="left">Left</div>
</div>
<body>

6.父級div 也一起浮動

所有元素一起浮動,就變成了一個整體,但會產生新的浮動問題。

<style type="text/css">
.div1{
    background:#000080;
    border:1px solid red;
    width:98%;
    margin-bottom:10px;
    float:left}
.div2{
    background:#800080;
    border:1px solid red;
    height:100px;width:98%;
    clear:both  /*解決程式碼*/}
.left{
    float:left;
    width:20%;
    height:200px;
    background:#DDD}
.right{
    float:right;
    width:30%;
    height:80px;
    background:#DDD}
</style>
<div class="div1">
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<div class="div2">
div2
</div>