【前端Talkking】 CSS系列——CSS深刻理解之float浮動

float屬性是CSS中經常使用的一個屬性,在實際工做中使用的很是多,若是使用不當就會出現意料以外的效果。雖然不少人說浮動會用就行、浮動過期了,可是對於優秀的前端開發人員,須要有"刨根問底"的精神,這樣在出現一些問題的時候纔不至於"手慌腳亂"!所以,今天就特別整理和總結一下float屬性。javascript

1. float介紹

CSS世界中的float屬性是一個年代很是久遠的屬性,設置了float屬性的元素會根據設置的屬性值向左或者向右浮動,直到它的外邊緣碰到包含框或另外一個浮動框的邊框爲止。設置了float屬性的元素會從普通文檔流中脫離,至關於不佔據任何空間,因此文檔中普通流中的元素表現的就像浮動元素不存在同樣,所以,設置float屬性的後會影響咱們的頁面佈局。具體說來就是:讓block元素無視float元素,讓inline元素像流水同樣圍繞着float元素實現浮動佈局css

float屬性設計的初衷:僅僅是讓文字像流水同樣環繞浮動元素,就像下圖中展現的同樣:html

WX20180422-132714@2x

2. float的特性

float有哪些有意思的特性呢?具體以下:前端

  • 包裹性
  • 高度塌陷
  • 塊狀化
  • 沒有任何margin合併

下面將詳細闡述這幾點的含義。java

2.1 包裹性

所謂"包裹性",實際上是由"包裹"和"自適應"兩部分組成。假設有如下CSS代碼:瀏覽器

/* CSS代碼 */
.father{
    border: 1px solid deeppink;
    width: 200px;
}
.son {
    float: left;
    font-size: 0;
    border: 1px solid blue;
    padding: 5px;
}
.father img {
    width: 128px;
}
複製代碼

1)包裹。本例中將浮動元素父元素寬度設置爲200px,浮動元素的子元素是一個128px寬度的圖片,則此時浮動元素寬度表現爲"包裹",也就是裏面圖片的寬度128px。微信

/* HTML代碼 */
<div class="father">
    <div class="son">
        <img src="../../lib/img/mm1.png">
    </div>
</div>
複製代碼

2)自適應性。在浮動子元素的中增長一些文字:app

/* HTML代碼 */
<div class="father">
    <div class="son">
        <img src="../../lib/img/mm1.png">
        <span style="font-size: 12px">美女1,美女2,美女3,美女4,美女5,美女6,後宮1,後宮2,後宮3,後宮</span>
    </div>
</div>
複製代碼

此時,浮動元素寬度就自適應父元素的200px寬度,最終的寬度表現也是200px。以下圖所示:佈局

自適應性

2.2 高度塌陷

float屬性有一個著名的特性:會讓父元素的高度塌陷。如章節2.1中的效果圖,父元素div的高度並無被子元素撐開(粉色區域),這種效果能夠稱爲"高度塌陷"。致使高度塌陷的緣由是由於浮動元素脫離了正常的文檔流,則div.father認爲其沒有子元素,因此產生了高度塌陷。後文中將講述如何解決高度塌陷的問題。學習

2.3 塊狀化

塊狀化的意思是,一旦元素float的屬性不爲none,則其display計算值就是block或者table。舉個例子:

/* JavaScript代碼 */
var span = document.createElement('span')
document.body.appendChild(span)
console.log('1.' + window.getComputedStyle(span).display)
// 設置元素左浮動
span.style.cssFloat = 'left'
console.log('2.' + window.getComputedStyle(span).display)
複製代碼

在控制檯中的結果以下:

1.inline
2.block
複製代碼

不知道你們有沒有跟我同樣的疑問:既然設置float後,元素就塊狀化了,那麼怎麼還能產生包裹性的效果呢?回答這個問題,須要從新闡述下塊狀化的意思,這裏的塊狀化意思是能夠像block元素同樣設置寬和高,並非真正的塊元素。

所以,沒有任何理由出現下面的樣式組合:

span{
    display: block; /* 多餘 */
    float: left;
}
span{
    float: left;
    vertical-align: middle; /* 多餘 */
}
複製代碼

2.4 沒有任何的margin重疊

在這裏,咱們將.son類增長margin:10px樣式,在瀏覽器中查看實際效果。

/* HTML 代碼 */
<div class="father">
    <div class="son">
        <img src="../../lib/img/mm1.png">
    </div>
    <div class="son">
        <img src="../../lib/img/mm1.png">
    </div>
    <div class="son">
        <img src="../../lib/img/mm1.png">
    </div>
</div>
複製代碼

沒有margin重疊

咱們增長.son類的margin爲10px,在瀏覽器中查看相鄰的.son元素的空白區域的高度是20px,能夠發現設置了float屬性的元素沒有任何的margin重疊,這和普通的元素margin重疊不同。

3. float與流體佈局

使用float能夠經過破壞正常的文檔流實現CSS環繞,可是卻帶來了"高度塌陷"的問題!然而咱們能夠利用float破壞正常文檔流的特性實現一些經常使用的佈局:

  • 文字環繞變身-中間內容居中,左中右佈局

直接看例子:

<div class="box">
    <a href="javascript:;" class="fl">左青龍</a>
    <a href="javascript:;" class="fr">右白虎</a>
    <h3 class="text-center">標題</h3>
</div>
複製代碼
.box{
    background-color: #f5f5f5;
}
.fl{
    float: left;
}
.fr{
    float: right;
}
.text-center{
    text-align: center;
}
複製代碼

從下圖中看出,實現了中間內容居中的左中右佈局。

青龍

  • 文字環繞的衍生-單側固定
<div class="father">
    <img src="../../lib/img/008.JPG">
    <p class="girl">美女1,美女2,美女3,美女4,美女5,美女6,後宮1,後宮2,後宮3,後宮4,後宮5,後宮6</p>
</div>
複製代碼
.father{
    border: 1px solid #444;
    overflow: hidden;
}
.father > img {
    width: 60px; height: 64px;
    float: left;
}
.girl {
    /* 環繞和自適應的區別所在 */
    margin-left: 70px;
}
複製代碼

和文字環繞效果相比,區別就是.girl多了一個margin-left: 70px,同時圖片的寬度設置60px,所以不會發生文字環繞的效果。這裏,咱們也能夠不使用margin-left,改用border-left或者padding-left均可以達到改變content box的尺寸,從而實現寬度自適應佈局效果。

單側固定

4. float的剋星

既然使用float屬性會帶來一系列的問題,那麼有沒有辦法消除這些問題呢?答案是:確定有。接着看下文。

4.1 clear屬性

在CSS中可使用clear來清除float屬性帶來高度塌陷等問題,使用格式以下:

clear: none | left | right | both
複製代碼
  • none:默認值,容許兩邊都有浮動對象;
  • left:不容許左側有浮動對象;
  • right:不容許右側有浮動對象;
  • both:兩側不容許有浮動對象。

若是單從字面上的意思來理解,clear:left應該是"清除左浮動",clear:right應該是"清除右浮動",實際上,這種說法是有問題的,由於浮動一直還在,並無清除!只能清除浮動帶來的影響。

官方對clear屬性的解釋是:"元素盒子的邊不能和前面的浮動元素相鄰"。注意這裏的"前面的"3個字,也就是clear屬性對"後面的"浮動元素是漠不關心的。clear屬性只能清除元素的自身,不能影響其餘的元素。接着看下面的這個例子:

/* HTML代碼 */
<div class="box1"></div>
<div class="box2"></div>
複製代碼
/* CSS代碼 */
.box1 {
    float: left;
    width: 100px;
    height: 60px;
    padding: 10px;
    border: 3px solid black;
    background: url("../../lib/img/mm1.png") center no-repeat;
}
.box2 {
    border: 3px solid red;
    padding:10px;
    width:100px;
    height: 60px;
    background: url("../../lib/img/mm2.jpg") center no-repeat;
}
複製代碼

浮動

如上圖所示,box1元素爲設置了左浮動,已經脫離了正常的文檔流,因此box2可以在box1的底層顯示。若是想讓box2可以換行排列,則只須要在.box2類中增長clear:left樣式便可。以下圖所示:

清除浮動

4.2 clear屬性的不足

clear屬性只對塊級元素有效,可是::after等僞元素默認都是內聯水平,所以,在實際工做中,咱們經常使用下面的代碼來清除浮動帶來的影響:

.clear::after{
    content: "";
    display: table;/*也能夠是'block'或者是'list-item'*/
    clear: both;
}
複製代碼

因爲clear:both做用的本質是讓本身不和float元素在一行顯示,並非真正意義上的清除浮動,所以float元素有一些很差的特性依然存在,表如今:

  • 若是clear:both元素前面的元素就是float元素,則設置margin-top無效;
/* HTML代碼 */
<div class="box1"></div>
<div class="box2"></div>
複製代碼
/* CSS代碼 */
.box1 {
    float: left;
    width: 100px;
    height: 60px;
    padding: 10px;
    border: 3px solid black;
    background: url("../../lib/img/mm1.png") center no-repeat;
}
.box2 {
    clear: both;
    margin-top: -20px;
    border: 3px solid red;
    padding:10px;
    width:100px;
    height: 60px;
    background: url("../../lib/img/mm2.jpg") center no-repeat;
}
複製代碼

在本例中,設置.box2中的margin-top沒有任何的效果,以下圖所示:

margin-top無效

  • clear:both後面的元素依舊可能會發生文字環繞現象。
<div class="father">
    <div class="float">
        <img src="../../lib/img/mm1.png">
    </div>
    <p>美女1,美女2,美女3,美女4,美女5,美女6,後宮1,後宮2,後宮3,後宮</p>
</div>
<div>我要美女1,我還要美女2</div>
複製代碼
/* CSS代碼 */
.father{
    border: 1px solid deeppink;
    width: 500px;
    height: 70px;
}
.father:after{
    content: '';
    display: table;
    clear: both;
}
.float{
    float: left;
}
.father img {
    width: 60px;
    height: 70px;
}
複製代碼

在本例中,設置clean:both來阻止浮動對後面元素的影響,可是最後的錯位效果依然發生了(能夠設置.father的字體大小爲0,而後設置p標籤的字體大小解決錯誤的問題)。

clean無效2

因而可知,clear:both只能在必定程度上消除浮動的影響,要想完美去除浮動元素的影響,藉助其餘的手段——BFC,接着看下文。

5. CSS世界的結界——BFC

5.1 BFC的定義

BFC全稱block formatting context,中文爲"塊級格式化上下文"。BFC的表現原則爲:若是一個元素具備BFC,那麼它的內部子元素再怎麼翻江倒海,都不會影響外部的元素。所以,BFC元素是不可能發生margin重疊的,另外,BFC元素也能夠用來清除浮動的影響。

那麼知足什麼條件纔會有BFC呢?只要知足下面任意一個條件就會觸發BFC:

  • html根元素;
  • float的值不爲none;
  • overflow的值爲auto、scroll或者hidden;
  • display的值爲table-cell、table-caption和inline-block中的任何一個;
  • position的值不爲relative和static;

觸發BFC後,就不須要使用clear:both屬性去清除浮動的影響。

5.2 BFC的做用

  • 清除margin重疊
/* HTML 代碼 */
<div class="parent">
    <p>item 1</p>
    <p>item 2</p>
    <p>item 3</p>
    <p>item 4</p>
</div>
複製代碼
/* CSS 代碼 */
.parent{
    width: 300px;
    background-color: black;
    overflow: hidden;
}
p {
    background-color: white;
    margin: 10px 0;
    text-align: center;
}
複製代碼

在這種狀況下,出現了margin重疊的效果。以下圖所示:

bfc

利用BFC能消除margin重疊,謹記:只有當元素在同一個BFC中時,垂直方向上的margin纔會clollpase。若是它們屬於不一樣的BFC,則不會有margin重疊。所以咱們能夠再創建一個BFC去阻止margin重疊的發生。因此爲了讓他們的margin變成20px,咱們只須要用div,創建一個BFC,令p元素處於不一樣BFC便可。請看例子:

/* HTML代碼 */
<div class="parent">
    <p>item 1</p>
    <p>item 2</p>
    <div style="overflow: hidden">
        <p>item 3</p>
    </div>
    <p>item 4</p>
</div>
複製代碼

從下圖中能夠看出,藉助BFC消除了margin重疊的問題。

bfc2

  • 清除高度塌陷的問題

在上面的章節中,若是子元素設置浮動屬性,則父元素就會出現高度塌陷的問題。在這裏,咱們能夠藉助BFC消除高度塌陷的問題了,請看下面的這個例子:

/* HTML代碼 */
<div style="border: 1px solid deeppink;width: 200px; overflow: hidden">
    <img src="../../lib/img/mm1.png" style="border: 1px solid blue; float: left">
</div>
複製代碼

從下圖中能夠看到,設置overflow:hidden樣式後就產生了BFC,根據BFC的表現規則,內部元素的樣式不會影響外部元素的樣式,所以沒有出現高度塌陷的問題。

overflowhidden

  • 自適應佈局(阻止文本換行)
/* HTML代碼 */
<div class="parent">
    <img src="../../lib/img/mm1.png">
    <p class="girl">美女1,美女2,美女3,美女4,美女5,美女6,後宮1,後宮2,後宮3,後宮4,</p>
</div>
複製代碼
/* CSS代碼 */
.parent{
    border: 1px solid deeppink;
    width: 200px;
    font-size: 0;
}
.parent img{
    border: 1px solid blue;
    float: left;
}
.girl{
    /*overflow: hidden;*/
    font-size: 12px;
    background-color: #cdcdcd;
}
複製代碼

若是咱們給.girl元素設置具備BFC特性的屬性,如:overflow: hidden就能夠實現更健壯、更智能的自適應佈局。

WX20180422-113834@2x

這裏的.girl元素爲了避免和浮動元素產生任何交集,順着浮動邊緣造成本身的封閉上下文。

普通元素在設置了overflow:hidden後,會自動填滿容器中除了浮動元素意外的剩餘空間,造成自適應效果,這種自適應佈局和純流體佈局相比:

  • 自適應內容因爲封閉而更加健壯,容錯性更強;
  • 自適應內容可以填滿除浮動元素之外區域,不須要關心浮動元素寬度。

6. 結語

本文是我學習float屬性總結文章,可能存在理解準確的地方,歡迎你們在評論區評論,指點迷津,你們互相幫助,互相進步。

最後,但願本文的內容可以對您對float的理解可以有所幫助,感謝閱讀。

ps:年初給本身定的計劃是爭取可以一週完成一篇文章,可是上一篇文章倒是2月19號的,不是我不想寫,實在是太累了!過完年一來,公司就實行強制加班,基本上是9105的節奏,並且整個公司實行部門加班時間排名。。。不想吐槽了。。。

參考

張鑫旭-《CSS世界》


碰見了,不妨關注下個人微信公衆號「前端Talkking」

公衆號底部二維碼_2018.04.22
相關文章
相關標籤/搜索