原文地址: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 小結
通過對比,我們不難發現,其實清除(閉合)浮動的方法無非有兩類:
清除浮動
:通過在浮動元素的末尾添加一個空元素,設置clear:both
屬性來清除浮動。after 僞元素其實也是通過在元素的後面生成了一個空白內容的塊級元素
閉合浮動
:通過設置父元素的 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;
}
效果圖:
若子元素有外邊距,父元素無外邊距,則會發生子元素外邊距越界現象
.para {
margin: 30px 0;
}
效果圖:
若父元素觸發了BFC,則會生成一個獨立的盒子包含子元素,包括子元素的外邊距
.container {
overflow: hidden; /* 觸發BFC */
}
效果圖:
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 */
}
效果圖:
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;
}
效果:
爲了解決這個問題,我們通過在容器中創建一個 BFC 包含浮動元素
.wrapper {
overflow: hidden; /* 創建BFC */
padding: 30px;
}
效果圖:
現在,這個容器的高度將擴展到可以包含它的浮動的子元素。在這個 BFC 中,這些元素將會回到頁面的常規文檔流
。
4 防止文字環繞
有時候一個浮動 div 周圍的文字環繞着它(如 Figure1 所示)。但是在某些場景中我們想要的效果如 Figure2 所示。爲了解決這個問題,我們可能使用外邊距,但是我們也可以使用一個 BFC 來解決。
首先讓我們理解文字環繞現象的產生原因:
上圖的 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;
}
效果圖:
讓我們創建 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;
}
效果圖:
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