CSS浮動float詳解

轉: https://www.jianshu.com/p/07eb19957991css

 
 

CSS裏浮動float是個概念比較曖昧的屬性,擼主最先對浮動float的認識是基於佈局的,認爲float元素就是用於:「讓block元素無視float元素,讓inline元素讓流水同樣圍繞着float元素」來實現浮動佈局。如今想一想,當初真是圖樣圖森破。html

其實這個屬性擼主一直是比較模糊的,感受似懂非懂。本着和本身死磕的精神,在參考了許多大神的博文後,將個人理解整理概括在本文中,但願能能夠幫助到你。固然擼主水平有限,若有錯誤敬請指出。前端

如下是網上大神關於float的優秀文章:編程

CSS浮動(float,clear)通俗講解瀏覽器

CSS float浮動的深刻研究、詳解及拓展(一)前端工程師

CSS float浮動的深刻研究、詳解及拓展(二)編程語言

那些年咱們一塊兒清除過的浮動wordpress

浮動float的本意:

傳統如C++,Java等編程語言一個API可能只能對應作一件事,即便有了模板和泛型編程,一般也只能作某一類事。但CSS是門至關靈活的語言。某個CSS屬性被用於的場景,可能會徹底違背當初創造該CSS屬性的本意。在CSS的世界裏,想實現某個效果,會有不少方法。那究竟選擇哪一種方法呢?有不少判斷標準,如重繪,如迴流,如極簡主義。擼主也有一個不成熟的判斷標準就是:根據該CSS屬性被創造時的本意,該用哪一個屬性就用哪一個屬性。
那浮動float的本意是什麼呢?是:讓文字像流水同樣環繞浮動元素。佈局

怎樣才能實現該效果呢?用 包裹性高度欺騙學習

特性一:包裹性

例1:首先來看浮動float的包裹性,所謂一圖勝千言:

 
 

相關代碼很是簡單:

<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
    <img src="img/25/2.jpg" />
</div>

 

所謂包裹性一目瞭然。block元素不指定width的話,默認是100%,一旦讓該div浮動起來,馬上會像inline元素同樣產生包裹性,寬度會跟隨內容自適應。(這也是一般float元素須要手動指定width的緣由)

再加上一個div的話,效果以下:

 
 
<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
    <img src="img/25/2.jpg" />
</div>
<div style="border:4px solid green;">
    <img src="img/25/3.jpg" /> 
</div>

 

效果很是近似於display:inline-block。但相比之下,浮動能設定爲左浮和右浮,但display:inline-block都是從左到右排列的。(還有些細微差異,兩個display:inline-block間會有空隙,但兩個float間沒有。這不是本篇的主題,暫時略過)

特性二:高度欺騙

(首先聲明:實際上是CSS層級在起做用,但CSS層級適合單獨寫一篇,內容實在太多,不適合在這裏展開,就理解爲高度欺騙吧)

例1中浮動float被設在了外圍div上,所以高度欺騙性沒體現出來。如今給內層img元素設定float。所謂一圖勝千言:


 
 
<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;">
    <img style="border:4px solid yellow;float:left;" src="img/25/2.jpg" />
</div>

 

和例子1惟一的區別就是:將外層div的float移到內層img中。這下高度欺騙性體現出來了。例1中給外層div加上浮動,所以外層div會有包裹性,其內容是img圖片,因此能夠看到紅色邊框包裹着img。

例2中外層div沒有了浮動,所以紅色邊框寬度默認是100%全屏。其內容img因爲加上了float,使得該img具備了欺騙性。float給img施了個障眼法,讓該img的inline-height高度塌陷爲0了。這樣外層div計算高度時,認爲img的高度爲0,至關於div的content的高度爲0,所以紅色邊框看起來是一條直線。

但請注意障眼法畢竟是障眼法,並非真的讓img的高度塌陷爲0了,能夠看到上圖中img的黃色邊框仍是有正常高度的。若是給div里加點文字,效果以下:

 
 

能夠看到,外層div在沒有手動設定height的前提下,其高度是由內部content的最大高度決定的,因爲img的float使得img具備高度塌陷的欺騙性,讓div誤覺得img的line-height爲0,所以div的高度就是文字的匿名inline-box的inline-height。

所以浮動並非讓元素的高度塌陷了,而是讓元素具備高度塌陷的欺騙性。騙誰?騙別人!但騙不了本身,元素自身仍是有高度的(見上圖的黃框)。

回過頭再看看浮動float的本意:讓文字像流水同樣環繞圖片。重要的事情多看幾遍...給div設定一個width:200px,並加點文字吧:

 
 

這就是浮動元素的本意。該效果是很難被其餘CSS屬性等價地模擬的。

但就像開頭說的,CSS強大的靈活性使得不少CSS屬性被用於了創造者都沒想到的場景。以float爲例,就被普遍用於了佈局。是好是壞呢?不知道!西紅柿臭雞蛋先別急着扔。既然擼主不知道,還廢話什麼?先看看float佈局的問題。渣浪微博改版前的好友列表用浮動佈局,效果以下:

 
 
<ul>
    <li style="width:138px;margin:0 10px;text-align: center;float:left;">
        <div><img src="img/25/1.jpg" />尼古拉斯.旺財</div>
    </li>
    <li style="width:138px;margin:0 10px;text-align: center;float:left;">
        <div><img src="img/25/2.jpg" />功夫熊貓</div>
    </li>
    <li style="width:138px;margin:0 10px;text-align: center;float:left;">
        <div><img src="img/25/3.jpg" />月野兔</div>
    </li>
    <li style="width:138px;margin:0 10px;text-align: center;float:left;">
        <div><img src="img/25/4.jpg" />貓女郎</div>
    </li>
</ul>

 

每一個li都設爲浮動和定寬,實現了水平佈局。但若是好友再長點呢?效果以下:

 
 

錯行啦!常見的修正方案是手動設定一個高度,讓文字固定顯示一行,用裁掉超行文字的代價以免錯行問題。在擼主看來這就是讓CSS屬性用於不合原意處的侷限性。設固定高度是OK,但若是哪天設計師以爲姓名須要顯示兩行呢,那固定高度就須要從新計算從新變。若是設計師以爲須要拓寬俄羅斯市場,姓名要顯示三行呢?再把固定高度改大點。若是將來Boss腦殼一拍,咦,能不能高度自適應呢?由姓名最大高度的好友來決定每行的高度。你是否是會有準備一下簡歷的衝動?

固然現實沒這麼誇張,高度自適應是個爛大街的技術,將浮動float改爲 display:inline-block 就好了,效果以下:

 
 

代碼只需將上面float:left;替換成display: inline-block;,沒對齊只需給li加上個vertical-align: top;(上面提到過,相比float,display:inline-block中間會有空隙,眼神好的能夠從圖中就能看出來,解決方案不是本篇的主題,能夠問度娘)。這下高度自適應了,每行的高度都是以名字最長的高度爲準。

回過頭看用float來水平佈局。是好是壞呢?好處是上手簡單,隨便什麼程度的CSSer都能搞定。壞處是有時須要定高難以自適應。而display:inline-block;屬性但是根正苗紅的水平佈局的屬性,能夠用其替代float。讓float儘可能多的幹其本職工做:讓文字像流水通常環繞浮動元素。因此擼主不知道答案。或許也根本沒有正確答案,不停的推翻原有的認識和想法人才能進步。

PS:用浮動佈局還有個壞處就是IE6下可能會有問題。但在IE6橫行時期,擼主經驗尚淺,如今項目裏早已明確棄用IE6,擼主也懶得挖墳驗證了。

清除浮動:

這個相對比較簡單了。用clear便可。稍微要注意的是,clear是僅做用於當前元素,例如元素A是浮動元素,靠左顯示。元素B是block元素緊跟在A後面。此時要清除浮動,是在B上設clear:left。你在A上設clear:right是沒有用的,由於A的右邊沒有浮動元素。

但真這麼簡單嗎?圖樣圖森破。

先明確一個概念,用clear確實能達到咱們指望的清除浮動的效果,這點沒異議。但深刻點看,到底是清除了什麼樣的浮動呢?一圖勝千言:

 
 

代碼:(給頁腳加上clear:left)

<div style="border:4px solid blue;">
    <div style="width:200px;border:4px solid red;float:left;">
        我是浮動元素1
    </div>
    <div style="width:200px;border:4px solid yellow;float:left;">
        我是浮動元素2
    </div>
</div>
<div style="border:4px solid gray;clear:left;">我是頁腳</div>

 

由於浮動元素的高度欺騙性,致使外層div失去了高度(藍色邊框成了一條線)。爲了讓頁腳顯示到浮動元素下面,對頁腳應用了clear:left。這是常規作法,沒有任何新奇之處。可是外層div的高度仍舊處於塌陷狀態,咱們腦海真真正指望的清除浮動後的樣子難道不是下面這樣嗎?

 

 
 
讓清除浮動後,本來被欺騙的外層div得到正確的高度!借用文首大神連接的說法,咱們腦中指望的其實並非上圖的清除浮動,而是下圖的 閉合浮動

 

閉合浮動

閉合浮動的實現方法不少,常見的是最後增長一個清除浮動的子元素:

<div style="border:4px solid blue;">
    <div style="width:200px;border:4px solid red;float:left;">
        我是浮動元素1
    </div>
    <div style="width:200px;border:4px solid yellow;float:left;">
        我是浮動元素2
    </div>
    <div style="clear:both;"></div>  //加上空白div節點來閉合浮動
</div>
<div style="border:4px solid gray;">我是頁腳</div>

 

缺點是會增長一個DOM節點。(話說當初擼主不知道在哪裏看到這個作法時,做者並未講這麼作的緣由,致使擼主不明白明明頁腳加一個clear屬性就能搞定的事,爲什麼要大動干戈加一個DOM節點)

方法二:一樣能夠在最後增長一個清除浮動的br:將上面代碼中<div style=」clear:both;」></div>替換成<br clear=」all」 />便可。語義上比空的div標籤稍微好一點,但一樣會增長一個DOM節點。

方法三:父元素設置 overflow:hidden(若是你還要兼顧IE6的話,加上*zoom:1;來觸發hasLayout)

<div style="border:4px solid blue;overflow:hidden;">
    <div style="width:200px;border:4px solid red;float:left;">
        我是浮動元素1
    </div>
    <div style="width:200px;border:4px solid yellow;float:left;">
        我是浮動元素2
    </div>
</div>
<div style="border:4px solid gray;">我是頁腳</div>

 

這看起來很奇怪。由於子元素的浮動的高度欺騙,致使父元素誤認爲content高度爲0(即藍色邊框爲一條線),因此父元素設成overflow:hidden溢出隱藏的話,直覺上應該子元素因爲溢出致使不顯示纔對,即整個頁面只顯示頁腳。但實際效果,父元素設成overflow:hidden溢出隱藏後,居然神奇地出現了閉合浮動的效果(藍色邊框正確得到了高度)。這是怎麼回事呢?靠的是BFC,但BFC提及來又是很長一篇,先略過。你能夠先簡單地這麼理解:瀏覽器廠商認爲要讓超出邊框部分能夠被修剪掉,那麼前提就是父元素要正確得到高度,即父元素不能被欺騙致使高度塌陷。瀏覽器正確得到子元素的高度後給父元素從新設置高度。雖然權威解釋確定是BFC,但擼主這樣理解了好久...

方法四:同上面將父元素設置 的overflow:hidden改爲auto,不贅述

方法五:父元素也設成float。這樣確實實現了閉合浮動,但頁腳將上移,因此頁腳仍舊須要clear:left。還有個缺點是因爲浮動的包裹性,你肯定父元素真的設成float對頁面佈局不會產生影響嗎?

方法六:父元素設置display:table。效果OK,頁腳也不須要設clear:left,但父元素的盒子模型被改變了,請先確認下這樣的改動對頁面佈局不會產生影響嗎?

方法七:用:after僞元素,思路是用:after元素在div後面插入一個隱藏文本」.」,隱藏文本用clear來實現閉合浮動:

.clearfix:after {
    clear: both;
    content: ".";   //你頭能夠改爲其餘任意文本如「abc」
    display: block;
    height: 0;      //高度爲0且hidden讓該文本完全隱藏
    visibility: hidden;
}
.clearfix {
    *zoom: 1;
}

 

<div style="border:4px solid blue;" class="clearfix">
    <div style="width:200px; border:4px solid red; float:left;">
        我是浮動元素1
    </div>
    <div style="width:200px; border:4px solid yellow; float:left;">
        我是浮動元素2
    </div>
</div>
<div style="border:4px solid gray;">我是頁腳</div>

 

這個方法很不錯,就是相比上面的方法,理解起來稍微有一點點難度。但也僅增長一點點而已。

總結:

第一篇文章囉嗦幾句。其實本文開頭連接的幾篇博文寫的比我好,爲什麼我要寫這篇博文?是我自信能比大神們寫的更好嗎?固然不是。之因此寫技術博文是由於這是一個很是好的學習總結的方式。就在寫以前我仍舊覺得已經很是瞭解float了,但真要提筆寫,又發現本身在很是多的細節方面仍是隻知其一;不知其二。只有真正靜下心來,邊思考邊作demo驗證邊總結,才能將本身的知識總結成一篇博文。

技術博文不是散文,必須條理清晰,結構嚴謹,經得起推敲,不能滿嘴跑火車,不然就誤人子弟了。之前看優秀的文章時,偶爾會看到做者吐槽:這段話足足寫了一下午。這篇文章寫了三天三夜。看着文章字數又很少,最多10分鐘就看完了,但若是你沒有真正提筆寫過,你可能體會不到期間的困難。

做爲一個起步很是晚的前端工程師(I know…I late to the Party.)我只能死磕本身。



做者:張歆琳
連接:https://www.jianshu.com/p/07eb19957991
來源:簡書


1 作着寫的很好
2 他也有和我相同的疑問(overflow:hidden),我沒去查,他查找後還本身總計了 
3 最後總結出,理解了不必定能寫出來
相關文章
相關標籤/搜索