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

接上回… php

5、浮動的非本職工做

浮動的本職工做是讓匿名inline boxes性質的文字環繞圖片顯示,而其餘全部用浮動實現的效果都不是浮動應該作的事情,我稱之爲「非本職工做」。 css

或許咱們並無過多的深思,把一些實際上不是浮動該乾的事情看成「這必須用浮動來實現」。舉個常見的例子,列表顯示,見下面的圖,截自淘寶新版首頁:
淘寶熱賣單品截圖 >> 張鑫旭-鑫空間-鑫生活
我不看代碼就知道是用浮動實現的,我用firebug一看,果真是,不只浮動,並且定寬。ps:要是在幾個月之前,我會以爲這實在有待改進,不過如今個人心態寬了,佈局思想不一樣而已,沒有孰對孰錯之分。
代碼截圖 web

我能夠確信,浮動這個屬性誕生的那天壓根沒有想到本身會要作這樣的事情,原本它覺得本身就讓文字環繞顯示就OK了,功德圓滿了,結果,在web2.0的時代,其卻在頁面佈局中被濫用。可能有人會反駁,你何處此言,有何證據? 瀏覽器

咱們只要靜下心來好好想一想浮動的本質,實現的原理,就能夠知道爲何浮動本不該該用來對頁面進行佈局。還記得上一部分所說的浮動的本質嗎?即「包裹與破壞」。咱們能夠用這個(「包裹與破壞」)解釋爲何浮動可讓li這類block水平的元素水平排列。 wordpress

單個無浮動的li元素 佈局

看下面的HTML代碼:
<ul style="width:440px;">
    <li style="border:4px solid #ff6633; background:#ffffc0;"><img src="../image/border.png" /></li>
</ul>

結果以下圖(截自Firefox瀏覽器,無其餘樣式干擾,下同):
來自張鑫旭-鑫空間-鑫生活 單個無浮動li元素 性能

這裏的li元素爲何會有高度?若是您認真讀過前半部份內容關於line boxes模型與高度的關係的內容,應該知道,因爲圖片沒有應用float屬性,其自己有一個正常的inline box,這個inline box高度等於圖片的height,在這行元素中,圖片這個inline box的高度最高,因而傳遞給了line box,line box是個真正意義上的高度,直接做用於containing box(就是這裏的li元素,使li元素有一個高度)。理解了這個您就會明白爲何要是這裏的圖片添加了float屬性,li高度會塌陷了:浮動破壞了inline box。這個後面會詳細講解。 測試

這裏的li沒有添加float屬性,能夠見到li寬度100%自適應於父ul標籤。一切顯得那麼的和諧! 網站

單個左浮動的li元素 spa

看下面的HTML代碼:
<ul style="width:440px;">
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
</ul>

結果以下圖:
來自張鑫旭-鑫空間-鑫生活 單個浮動li元素

相比上面而言,這裏多了個float:left;,浮動的「包裹性」一目瞭然:水平方向上,li寬度緊貼內部元素。我在前文曾說過這麼句結論性的話:「撇開浮動的‘破壞性’,浮動就是個帶有方位的display:inline-block屬性」。這不難理解,您能夠講這裏的float:left;改爲display:inline-block;最後實現的效果基本上就是同樣的。display:inline-block將對象呈遞爲內聯對象,可是對象的內容做爲塊對象呈遞。所謂對象呈遞爲內斂對象就是元素呈遞爲inline box,因此浮動「包裹性」所產生的結果就是使得元素轉爲了line box模型中的inline box元素。

浮動的「包裹性」讓元素變成相似於inline box的元素,而浮動的「破壞性」正是破壞inline box元素的,這其中豈不有矛盾。其實非也,對於block水平的這類塊狀元素須要先讓其變成相似效果的內聯元素,而後再破壞之,實乃先誘拐再姦殺的生動實例啊!

又是我反覆提到的,浮動破壞了inline box,也就是破壞了高度,因此這裏含有浮動屬性的li元素其實是沒有高度的。因此呢,要是後面還有一樣的li標籤的話,就會水平對齊排列的。以下:

多個左浮動的li元素

看下面的HTML代碼:
<ul style="width:440px;">
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
</ul>

結果以下圖:
來自張鑫旭-鑫空間-鑫生活 多個浮動li元素

左浮動的li元素和無浮動的li元素

看下面的HTML代碼:
<ul style="width:440px;">
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
    <li style="border:4px solid #ff6633; background:#ffffc0;"><img src="../image/border.png" /></li>
</ul>

結果以下圖:
來自張鑫旭-鑫空間-鑫生活 左浮動的li元素和無浮動的li元素

後面一個li無float屬性,直接無視前面的float li元素,寬度100%顯示,並且與float屬性的li同一水平線排列,爲什麼?由於浮動破壞了li的實際高度(緣由我講得太屢次了),只是圖片是個實體,沒法與一樣實體的同一文檔流的圖片重合,因此圖片靠在一塊兒。

6、證據

1. 首要證據

前文是着重分析了浮動的「本職工做」:文字環繞顯示;本文着重分析了浮動的「非本職工做」:列表佈局;二者都是用的一樣的原理解釋的,那麼有什麼證據能夠證實「頁面佈局」不是浮動的「本職工做」呢。答案關鍵字就是:高度塌陷

我在多個地方濃墨重彩的講浮動與高度的關係,浮動使高度塌陷的緣由,本身都以爲嘮叨的太多了,這裏再也不講。直接講些實際的東西。

您是否發現,浮動佈局會讓父標籤高度缺失,可是實現文字環繞圖片效果的時候父標籤無需清除浮動。仍是上面的例子,咱們看看多li元素浮動時ul標籤高度在哪裏,咱們能夠給ul加個邊框屬性作測試,測試代碼以下:

<ul style="width:440px; border-top:4px solid #a0b3d6; border-bottom:4px solid #34538b;">
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
    <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li>
</ul>

結果以下圖:
來自張鑫旭-鑫空間-鑫生活 浮動元素父標籤高度

上圖顯示ul高度爲0,這是必然的,正常的,應該的。您要是在IE下看到ul有高度,認爲這是Firefox等瀏覽器有問題就錯了,您把ul的width屬性去掉,看看,會發現IE下ul高度也爲0, 這是IE的layout做祟。至於爲何ul高度爲0,我前面不少地方都已經講了,再也不說了。可是,從中咱們能夠看到,浮動本不是用來列表佈局的,而是用來使元素環繞顯示的,由於元素環繞(例如文字),其自身是含有inline boxes高度的,這是inline水平的元素造成高度的基礎,因此,雖然浮動元素沒有高度,可是其周圍環繞的元素是有高度的,只要環繞元素比浮動元素高度高,父標籤無高度的問題天然也就沒有了,可是純粹一堆浮動元素會有高度嗎?沒有。因此浮動元素塌陷的問題根本就不是瀏覽器的bug,而是咱們沒有正確地深刻地瞭解浮動,是咱們本身使用不當,由於浮動本不該該用在這裏的。

2. 其餘證據

爲何說浮動的本職工做不是頁面佈局而應該是是元素環繞呢。還有其餘些證據。

歷史

CSS剛誕生的時候,那時候的網頁仍是表格佈局的時代,能顯示幾張圖片就不錯了,複雜的列表顯示,佈局啊這些概念仍是很淡薄的,浮動出現的意義就是讓文字可以環繞圖片顯示而已,就如word般。

現象

Google是目前互聯網領域的老大,技術很牛叉,毋庸置疑,可是,當我發現它全部的頁面幾乎都是表格佈局的時候,很詫異;還有twitter,也是表格佈局的;
twitter表格佈局 >> 張鑫旭-鑫空間-鑫生活
爲何這些頂尖的web網站使用表格佈局,而不跟隨潮流呢,起初我是百思不得其解。如今,我是明白了,這麼作是有他的道理的,難道要用一堆浮動的元素去佈局嗎?這不是浮動該乾的事情。並且,浮動是個很很差惹的魔鬼。

7、浮動是個魔鬼、混球

浮動的存在就是個破壞。浮動效果的實現就是先破壞自身(揮刀自宮),而後影響別人。頁面中只要出現一個浮動,勢必有其餘元素受其影響。這是開發和維護中的一個定時炸蛋(敏感詞)。咱們想一想浮動的意義,只是讓文字環繞圖片顯示而已,因此其必須破壞自身模型和高度。可是,不知道幸運仍是不幸,浮動的這種置之死地然後生的特性竟然可讓元素佈局,加上其表面意思很好理解,兼容性還不錯,使用方便,因而在捨棄了table佈局的這個web時代裏,浮動成爲當前頁面佈局的主流。想一想,真是一件可怕的事情。

有些人可能沒有意識到浮動實際上是個很糟糕的東西,是CSS中的一個魔鬼。爲何,或許由於用浮動佈局頁面發現還行,即便偶爾出現些小bug,打打補丁也能夠解決。或許是由於沒有體會到非浮動元素和浮動元素在開發和維護上所消耗的成本精力的差異。有些人可能知道浮動這個屬性能不用就不用,可是因爲找不到更好的替代方法,因此仍是有不少地方使用了浮動佈局,例如選項卡,列表顯示等。

理論上而言,除了浮動的環繞效果以外,咱們使用浮動作的其餘工做均可以使用別的CSS屬性實現,並且大部分狀況是比浮動的效果好:首先沒有了清楚浮動一說,二是有關浮動的一堆bug也不會出現,三是元素間獨立了,不會像浮動同樣改變一個會影響其餘。可是,考慮到大多數人對CSS掌握的程度,以及瀏覽器的一些兼容性問題等,不少時候,咱們不得不使用看上去使用方面但潛在問題較大的浮動屬性。因此,有關浮動的一些特性的研究仍是頗有必要的,這就是下面的重點。

8、解決高度塌陷的問題 – 清除浮動

CSS中有個討論較多的話題就是如何清除浮動,清除浮動其實就一個目的,就是解決高度塌陷的問題。爲何會高度塌陷?何時會高度塌陷?塌陷緣由是:元素含有浮動屬性 – 破壞inline box – 破壞line box高度 – 沒有高度 – 塌陷。何時會塌陷:當標籤裏面的元素只要樣子沒有實際高度時會塌陷。因此呢,並非只要有浮動元素就會坍塌,就要清除的,CSS水平高低衡量的標準之一就是改用什麼樣式就用什麼樣式,很少用也很多用。

下面就來說講如何清除浮動,zxx:寫到這兒,一會兒輕鬆了。
IE下清除浮動準則很簡單,使元素haslayout就能夠了。如寬度值,高度值,絕對定位,zoom,浮動自己均可以讓元素haslayout。顯然,首選zoom:1;不會干擾任何樣式。非IE瀏覽器經常使用的是overflow屬性,overflow:hidden;或是overflow:scroll均可以,不過因爲後者常常一不當心出現滾動條,因此前者用的更多些。因爲現代瀏覽器都支持after僞類,因此經常也會用after寫入一個clear屬性的元素清除浮動。固然,最投機取巧的方法就是直接一個<div style="clear:both;"></div>放到看成最後一個子標籤放到父標籤那兒。下面小結這幾個方法。

1. 投機取巧法

就是直接一個<div style="clear:both;"></div>放到看成最後一個子標籤放到父標籤那兒,此方法屢試不爽,兼容性強,使用方便,是初學時使用的上佳之選。可是我歷來不用,由於我看到的是個巨大的浪費,浪費了一個標籤,並且只能使用一次,我我的是沒法容忍的,因此這個方法不推薦。並且有時候一不留神中間多了個空格會產生一段空白高度的。

2. overflow + zoom方法

.fix{overflow:hidden; zoom:1;}

此方法優勢在於代碼簡潔,涵蓋全部瀏覽器,可謂不錯的選擇啊。不過也是有問題的,就是這個overflow:hidden;是個小炸蛋,要是裏面的元素要是想來個margin負值定位或是負的絕對定位,豈不是直接被裁掉了,因此此方法是有不小的侷限性的。我通常不用這個方法,只是有時候順便去除浮動時用用。

3. after + zoom方法

先來簡單講講after,所謂after,就是指標籤的最後一個子元素的後面。因而呢,咱們能夠用CSS代碼生成一個具備clear屬性的元素,其中的關鍵樣式就是content了。或許您從網上看到的content裏面的內容是」.」一個點,我了不少次,貌似隨便寫什麼東西都沒有問題,好比content:'clear both';沒問題,或是content:'張鑫旭'也是ok的。因而有:
.fix{zoom:1;}
.fix:after{display:block; content:'clear'; clear:both; line-height:0; visibility:hidden;}

這裏的line-height:0寫成height:0也是能夠的。此方法能夠說是綜合起來最好的方法了,我都是用這個樣式清除浮動的,不會影響任何其餘樣式,通用性強,覆蓋面廣,我很推薦哦。

9、float與JavaScript

JavaScript能夠改變CSS的屬性,其餘些屬性還好,可是這個float值得一說,爲什麼呢,由於float貌似是JavaScript中的一個關鍵字,不能使用obj.style.float="left";這樣的句子。得使用其餘寫法。

IE瀏覽器:
obj.style.styleFloat = "left";

其餘瀏覽器:

obj.style.cssFloat = "left";

10、最後的總結

其實本來是想經過深刻分析浮動的前世此生,本質意義來揭示其醜陋的真面目的,多是在文字表達上還欠火候,總以爲表達的有些凌亂,估計很輕鬆就知道我在說什麼的人較少,原本是篇頗有技術含量的文章,可是在表現上作的不夠好,多是內容太多,本身想要表達的內容太多,因而反而有些混亂。因此,最後其實不少東西沒有繼續詳細展開講解,例如清除浮動的本質是什麼?浮動產生一系列bug的根本緣由是什麼?浮動佈局更好的替代方案是什麼?由於內容已經夠多夠亂的了,因此我決定這些內容留到之後,思路清晰的時候再表述出來。

本文能夠說是有別於目前絕大多數關於浮動的文章,我沒有講浮動的使用實例啊之類的東西,也沒有去分析浮動的一些特性,僅僅從最根本的地方分析浮動,我想這個比單純的講解幾個浮動的應用做用更深遠。並且還有一點,本文其實某種程度上是批判浮動的,但願開發者儘量的少使用浮動,少使用浮動去作些其實並非浮動應該作的事情。因此要是花功夫講浮動的應用的話就是搬石頭砸本身的腳。

本文不少理論的東西,可能是本身的我的看法,因此實際上有些認識多是不許確的,歡迎有不一樣觀點的同行們反駁,也歡迎交流(經過評論或是去這裏進行提問交流)。

轉載自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
(本篇完)

相關文章
相關標籤/搜索