【轉】CSS FLOAT 學習筆記

原文地址:http://www.w3ctech.com/topic/1551

原文如下:

FLOAT

@Keywords: Float Clearfix ::after BFC hasLayout

@Author: GreenMelon @吾南蠻野人 陳燦堅

@分享地址:http://pan.baidu.com/s/1eQqagt8

@Date: 二O一五.十月.24th

[TOC]

CSS的定位機制

  • 常規流(Normal-Flow)
  • 浮動(Float)
  • 絕對定位(Absoluted Position)

浮動的特性

  • 浮動框可以左右浮動,直至它的外邊緣遇到包含框或者另一個浮動框的邊緣
  • 浮動框脫離了文檔的常規流。文檔的常規流就會忽略浮動框的存在
  • 浮動框不會影響到塊級框的佈局,但會影響內聯框的排列
  • 當浮動框高度超出包含框的時候,包含框不會自動伸縮來閉合浮動框。如果包含框內部不存在其他普通流元素,其高度爲0。即所謂的高度塌陷現象

浮動的分類

  • 清除浮動: Clearing-Float,浮動元素的左右兩邊是否允許其他元素的存在
  • 閉合浮動: Enclosing-Float,浮動元素重新被包含進父元素(閉合浮動的目的在於使包含框表現出正常的高度)

清除(閉合)浮動的方法

1 clear清除法

1.1 添加空元素

我們先來看一個典型的浮動的例子

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
</div>
<div class="wrapper-siblings">wrapper-siblings</div>
body {
  font-size: 32px;
  text-align: center;
  color: #fff;
}
.wrapper {
  background-color: green;
}
  .float-left,
  .float-right {
    width: 40%;
    height: 100px;
    line-height: 100px;
    background-color: orange;
  }
  .float-left {
    float: left;
  }
  .float-right {
    float: right;
  }

.wrapper-siblings {
  height: 100px;
  line-height: 100px;
  background-color: crimson;
}

由於 .wrapper 的兩個子元素 .float-left 和 .float-right 浮動,造成 .wrapper 的高度坍塌現象:

點擊 demo 查看

我們可以在浮動元素末尾添加一個空元素來清除浮動:

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
  <!-- 添加空元素 -->
  <div class="clear"></div>
</div>
<div class="wrapper-siblings">wrapper-siblings</div>
  /* For modern browsers */
  .clear {
    clear: both;  /* 清除左右浮動 */
  }

  /* For IE browsers */
  .clear {
    clear: both;
    height: 0;
    line-height: 0;
    font-size: 0;
  }

效果圖:

點擊 demo 查看

優點:簡單易用

缺點:增加了無意義的空標籤,有違語義化,有違結構與表現相分離,不利於後期維護

1.2 使用br元素

我們也可以使用 br 元素,利用 br 元素的 clear = all | left | right | none 屬性

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
  <!-- 使用br元素 -->
  <br clear="all">
</div>
<div class="wrapper-siblings">wrapper-siblings</div>
body {
  font-size: 32px;
  text-align: center;
  color: #fff;
}
.wrapper {
  background-color: green;
}
  .float-left,
  .float-right {
    width: 40%;
    height: 100px;
    line-height: 100px;
    background-color: orange;
  }
  .float-left {
    float: left;
  }
  .float-right {
    float: right;
  }

.wrapper-siblings {
  height: 100px;
  line-height: 100px;
  background-color: crimson;
}

效果圖:

點擊 demo 查看

如果在父元素外部使用 br 元素:

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
</div>
<!-- 在外部使用br元素 -->
<br clear="all">
<div class="wrapper-siblings">wrapper-siblings</div>

高度坍塌現象仍然存在:

點擊 demo 查看

優點:比空元素方式語義稍強

缺點:同樣增加了無意義的空元素,不利於後期維護

1.3 使用僞元素::after

NOTE: 由於 IE6-7 不支持 ::after,使用 zoom: 1; 觸發 hasLayout

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
</div>
<div class="wrapper-siblings">wrapper-siblings</div>
body {
  font-size: 32px;
  text-align: center;
  color: #fff;
}
.wrapper {
  margin-bottom: 10px auto;
  background-color: green;
}
.wrapper::after {
  content: "";  /* 空內容的默認高度爲0,避免生成的內容破壞原有佈局的高度 */
  display: block;  /* 使生成的內容以塊級元素顯示,佔滿剩餘空間 */
  height: 0;  /* 當內容不爲空時,設置0高度,避免生成的內容破壞原有佈局的高度 */
  visibility: hidden;  /* 使生成的內容不可見,避免影響被其蓋住的內容的交互事件 */
  clear: both;  /* 關鍵:清除左右浮動 */
}
  .float-left,
  .float-right {
    width: 40%;
    height: 100px;
    line-height: 100px;
    background-color: orange;
  }
  .float-left {
    float: left;
  }
  .float-right {
    float: right;
  }

.wrapper-siblings {
  height: 100px;
  line-height: 100px;
  background-color: crimson;
}

效果圖:

點擊 demo 查看

優點:結構和語義化都正確

缺點:複用方式不當會造成代碼量增加

2 觸發BFC

2.1 父元素 overflow: hidden | auto;

通過設置父元素 overflow 的值爲 visible 以外的值,從而觸發 BFC;在 IE6 中還需要觸發 hasLayout,例如 zoom: 1;

<div class="wrapper">
  <div class="float-left">float-left</div>
  <div class="float-right">float-right</div>
</div>
<div class="wrapper-siblings">wrapper-siblings</div>
body {
  font-size: 32px;
  text-align: center;
  color: #fff;
}
.wrapper {
  overflow: hidden;  /* 觸發BFC */
  background-color: green;
}
  .float-left,
  .float-right {
    width: 40%;
    height: 100px;
    line-height: 100px;
    background-color: orange;
  }
  .float-left {
    float: left;
  }
  .float-right {
    float: right;
  }

.wrapper-siblings {
  height: 100px;
  line-height: 100px;
  background-color: crimson;
}

效果圖:

點擊 demo 查看

優點:不存在結構和語義化問題

缺點:內容過多時,不會自動換行導致內容被隱藏掉,無法顯示需要溢出的元素

2.2 其他方式

我們也可以使用其他方式觸發BFC,效果和使用 overflow 類似。在後面的關於 BFC 的介紹中,我們再詳細闡述。

3 小結

通過對比,我們不難發現,其實清除(閉合)浮動的方法無非有兩類:

  1. 清除浮動:通過在浮動元素的末尾添加一個空元素,設置 clear:both 屬性來清除浮動。after 僞元素其實也是通過在元素的後面生成了一個空白內容的塊級元素

  2. 閉合浮動:通過設置父元素的 overflow 等屬性觸發 BFC 來閉合浮動

BFC

BFC: Block Formatting Contexts (塊級格式化上下文,CSS3 改稱爲 Flow Root)

BFC 是 Web 頁面中盒模型佈局的 CSS 渲染模式。它的定位體系屬於常規文檔流。通俗地講:創建了 BFC 的元素就是一個獨立的盒子,裏面的子元素不會在佈局上影響外面的元素,同時 BFC 仍然屬於文檔中的常規流。

BFC的觸發條件

  • position: absolute | fixed;
  • display: table-caption | table-cell | inline-block | inline-flex | flex;
  • float: left | right;
  • visibility: hidden | scroll | auto;

BFC的特性

BFC的用途

1 父元素的高度值

默認的 web 佈局

<div class="container">
  <p class="para">Sibling 1</p>
  <p class="para">Sibling 2</p>
</div>
body {
  font-size: 24px;
  text-align: center;
  color: #fff;
}
.container {
  margin: 0;
  background-color: crimson; 
}
  .para {
    height: 50px;
    line-height: 50px;
    background-color: orange;
  }

效果圖:

Alt text

若子元素有外邊距,父元素無外邊距,則會發生子元素外邊距越界現象

  .para {
    margin: 30px 0;
  }

效果圖:

Alt text

若父元素觸發了BFC,則會生成一個獨立的盒子包含子元素,包括子元素的外邊距

.container {
  overflow: hidden;  /* 觸發BFC */
}

效果圖:

Alt text

2 防止外邊距重疊

在上面,我們已經看到了子元素的外邊距重疊現象。如何防止呢?我們必須牢記在心的是:毗鄰的塊盒的垂直外邊距重疊只有當它們是在同一BFC時纔會發生。如果它們屬於不同的BFC,那麼外邊距將不會重疊。所以通過創建一個新的 BFC 我們可以防止外邊距重疊。

<div class="container">
  <p class="para">Sibling 1</p>
  <p class="para">Sibling 2</p>
  <!-- 創建新的BFC -->
  <div class="new-bfc">
    <p class="para">Sibling 3</p>
  </div>
</div>
body {
  font-size: 24px;
  text-align: center;
  color: #fff;
}
.container {
  margin: 0;
  overflow: hidden;  /* 創建BFC */
  background-color: crimson; 
}
  .para {
    height: 50px;
    line-height: 50px;
    margin: 30px 0;
    background-color: orange;
  }
  .new-bfc {
    overflow: hidden;  /* 創建新的BFC */
  }

效果圖:

Alt text

3 閉合浮動

一個 BFC 可以包含浮動元素。很多時候我們會碰到這種情況:一個容器裏的浮動元素脫離頁面的常規流,導致容器的高度坍塌。我們通常使用僞元素來清除浮動。但我們同樣可以通過定義一個 BFC 來達到這個目的。

<div class="wrapper">
  <div class="floated">floated</div>
  <div class="floated">floated</div>
  <div class="floated">floated</div>
  <div class="floated">floated</div>
  <div class="floated">floated</div>
</div>
.wrapper {
  border: 5px solid green;
  background-color: crimson;
}
.floated {
  float: left;
  width: 15%;
  height: 100px;
  border-radius: 5px;
  margin: 0 30px;
  text-align: center;
  line-height: 100px;
  background-color: orange;
}

效果:

Alt text

爲了解決這個問題,我們通過在容器中創建一個 BFC 包含浮動元素

.wrapper {
  overflow: hidden;  /* 創建BFC */
  padding: 30px;
}

效果圖:

Alt text

現在,這個容器的高度將擴展到可以包含它的浮動的子元素。在這個 BFC 中,這些元素將會回到頁面的常規文檔流

4 防止文字環繞

有時候一個浮動 div 周圍的文字環繞着它(如 Figure1 所示)。但是在某些場景中我們想要的效果如 Figure2 所示。爲了解決這個問題,我們可能使用外邊距,但是我們也可以使用一個 BFC 來解決。

Alt text

首先讓我們理解文字環繞現象的產生原因:

Alt text

上圖的 HTML Markup 如下所示:

<div class="container">
  <div class="floated">Floated div</div>
  <p>Quae hic ut ab perferendis sit quod architecto,dolor debitis quam rem provident aspernatur tempora expedita.</p>
</div>

在上圖中的整個黑色區域爲 p 元素。正如我們所看到的,由於這個 .floated 浮動了,脫離了常規文檔流,不佔空間。因此 p 元素自動上移,佔據 .floated 原有的空間。因此 p 元素出現在 .floated 的下方。浮動框不會影響塊級框的佈局,但是會影響內聯框的排列。因此 p 元素的 line boxes(文本行) 水平收縮進行了移位,爲浮動元素提供了空間。隨着文字的增加,因爲 line boxes 不再需要移位,最終將會環繞在浮動元素的下方。

讓我們回顧W3C 的標準:

在 BFC 中,每個盒子的左外邊框緊挨着包含塊的左邊框(從右到左的場景中,則爲右邊框緊挨着包含塊的右邊框),即使在浮動裏也是這樣的(儘管一個盒子的邊框會因爲浮動而萎縮)。除非這個盒子的內部創建了一個新的BFC(這種情況下,由於浮動,盒子本身將會變得更窄)

根據標準,如果這個 p 元素創建了一個新的 BFC,那麼它將不會緊挨着容器塊的左邊緣。這樣就解決了文字環繞在浮動元素周圍的問題。

讓我們從文字環繞的佈局開始:

<div class="container">
  <div class="floated">Floated</div>
  <p class="para">Quae hic ut ab perferendis sit quod architecto,dolor debitis quam rem provident aspernatur tempora expedita.</p>
</div>
.container {
  width: 300px;
  padding: 20px;
  border-radius: 5px;
  font-size: 24px;
  background-color: crimson;
}
  .floated {
    float: left;
    width: 40%;
    height: 150px;
    border-radius: 5px;
    text-align: center;
    line-height: 150px;
    background-color: orange;
  }
  .para {
    padding-left: 10px;
    margin: 0;
    color: #fff;
  }

效果圖:

Alt text

讓我們創建 BFC 解決文字環繞現象:

.container {
  width: 300px;
  padding: 20px;
  border-radius: 5px;
  font-size: 24px;
  text-align: center;
  background-color: crimson;
}
  .floated {
    float: left;
    width: 40%;
    height: 150px;
    border-radius: 5px;
    line-height: 150px;
    background-color: orange;
  }
  .para {
    overflow: hidden;  /* 創建BFC */
    padding-left: 10px;
    margin: 0;
    color: #fff;
  }

效果圖:

Alt text

IE6-7的 hasLayout

IE 的 hasLayout 與 BFC 類似。IE6-7 的顯示引擎使用一個稱爲佈局(layout)的內部概念來控制元素的尺寸和定位。那些 hasLayout 的元素負責本身及其子元素的尺寸設置和定位。如果一個元素的 hasLayout 爲 false,那麼它的尺寸和定位由最近的擁有佈局的祖先元素控制。

hasLayout的觸發條件

  • position: absolute;
  • display: inline-block;
  • float: left | right;
  • width: 非auto
  • height: 非auto
  • zoom: 非normal
  • writing-mode: tb-rl;
  • overflow: hidden | scroll | auto; (IE7特有)

IE8 使用了全新的顯示引擎,據稱不使用 hasLayout 屬性了,因此解決了很多深惡痛絕的 bug。但 IE8-11 通過「document.documentElement.currentStyle.hasLayout」依然可以獲得 hasLayout 的標誌。

小結

綜上所述,在支持 BFC 的瀏覽器(IE8+,firefox,chrome,safari)通過創建新的 BFC 閉合浮動;在不支持 BFC 的瀏覽器(IE6-7)通過觸發 hasLayout 閉合浮動。

清除(閉合)浮動的優化方法

  • 優化1
    /* For IE 6/7 only */
    .clearfix {
    *zoom: 1;
    }
    /* For modern browsers */
    .clearfix::after {
    content: "200B";  /* 零寬度空格的Unicode字符 */
    display: block;
    height: 0;
    clear: both;
    }
  • 優化2
    /* For IE 6/7 only */
    .clearfix {
    *zoom: 1;
    }
    /* For modern browsers */
    .clearfix::before,  /* before用於處理垂直邊距疊加,視情況而定可不加 */
    .clearfix::after {
    content: "";
    display: table;
    }
    .clearfix:after {
    clear: both;
    overflow: hidden;
    }
    reference: A new micro clearfix hack

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