W3C規(guī)范推薦在容器底部添加一個clear:both的元素
開篇:什么是CSS清除浮動,為什么要清除浮動?
»什么是CSS清除浮動?
網(wǎng)絡(luò)上流行的說法是:在非IE瀏覽器(如Firefox)下,當容器的高度(height)為auto,且容器的內(nèi)容中有浮動(float為left或right)的元素,在這種情況下,容器的高度不能自動伸長以適應(yīng)內(nèi)容的高度,使得內(nèi)容溢出到容器外面而影響(甚至破壞)布局的現(xiàn)象。這個現(xiàn)象叫浮動溢出,為了防止這個現(xiàn)象的出現(xiàn)而進行的CSS處理,就叫CSS清除浮動。
»出現(xiàn)浮動溢出的條件是什么?
首要條件:height:auto,或者說高度是自動伸展的。
傳統(tǒng)觀念:只有Firefox和Opera才需要進行浮動清除。
很抱歉,IE6和IE7都會。
下面這個浮動溢出的例子就是在IE6/IE7,Firefox和Opera下都會出現(xiàn)浮動溢出:浮動溢出的例子
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?
點擊查看:
浮動溢出的條件?點擊查看:
清除浮動的最佳方法!»為什么要CSS清除浮動和需要一個怎樣的方法?
實現(xiàn)容器高度隨內(nèi)容自動伸縮而不受其它內(nèi)外元素影響。
通過編寫CSS簡單實現(xiàn),不用編寫Javascript。
尋找一個方法:為實現(xiàn)浮動清除,盡量不要對容器作太多的修改。
這個方法盡量從外觀樣式中獨立分離,不耦合于樣式中,純粹,不易受改變(健壯),可重用性強(這也是CSS好處之一)。
幾個關(guān)鍵詞
[?]容器:布局中用于把細小內(nèi)容組織起來的元素,在這里指內(nèi)有浮動元素,且要求自身的高度不得小于浮動元素高度的元素。
浮動層:指設(shè)置了CSS屬性float為"left"或者"right"的元素。
清除浮動:實現(xiàn)容器高度能隨其內(nèi)容浮動層高度而擴展拉伸,不讓浮動層溢出。
方法一(W3C規(guī)范?):只要最底部有一個clear:both的元素?
這里的 容器2 就是紅邊框的最后一個元素了,且clear為both了,只是在非IE下依然不能解決問題。
如果該元素內(nèi)部又出現(xiàn)一個浮動元素的話,就不行了,如 容器2 內(nèi)的一個float:right的元素。
效果展示1:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?注:
[?]Opera9.27下這里的margin-top居然不起作用,一直粘著上面的浮動層走,不過這對主要問題說明影響不大。
關(guān)于margin-top:
[?] 在有浮動的情況下,元素的margin-top是從上一個非浮動的元素開始計算的。而對
easyclearing.html上說到的,“從上一個clear過的元素開始計算”的說法,我有所保留。不信大家在容器 container_2 前面加些標簽或者文字改變一下它的高度試試。
我認為,W3C規(guī)范說的“在容器底部添加一個可識別的clear元素”,被人們斷章取義地理解錯了,才會出現(xiàn)效果展示1這樣的誤會?;蛘?a target="_blank" >Easyclearing.html就是誤會之源。
正確的理解:在所有需要進行浮動清除的容器的底部添加一個可識別的clear元素。
[?] 如何理解上面的話?
請看回效果展示1,“容器2”是“大容器(紅邊框)”里的最后一個“clear 過的、可識別的”元素。不錯,但“容器2”也是容器啊,它也需要清除浮動啊,為什么不一視同仁,為“容器2”也添加一個“可識別的clear元素”?如果 新添加的這個“可識別的clear元素”內(nèi)也有浮動元素呢?再添加一個,如此之般,直到人們再也不想在“可識別的clear元素”內(nèi)添加浮動的東西為止, 問題不就解決了?
||--(好啰嗦的話呀~)
基于這個理解,請看方法二。
方法二(可行):添加一個 clear:both 的 空元素
即在容器的最后添加一個<div style="clear:both;"></div>
只要這個clear元素里面什么也不放,就不會出現(xiàn)上面的問題啦。
效果展示2:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。這是個clear:both的空元素,為了看得出來,我還是了加點修飾。
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?這是個clear:both的空元素,為了看得出來,我還是了加點修飾。
即在容器的最后添加一個<div style="clear:both;"></div>
只要這個clear元素里面什么也不放,就不會出現(xiàn)上面的問題啦。
不只是div,好些元素也可以用來做clear,看你怎么想了,這時在CSS中最好這樣寫(出自
from some body I forgot): 代碼展示1:
html body .clear, html body div.clear, html body span.clear, html body li.clear, html body dd.clear { background: none; border: 0; clear: both; display: block; float: none; font-size: 0; list-style: none; margin: 0; padding: 0; overflow: hidden; visibility: hidden; width: 0; height: 0; line-height: 0; font-size: 0; } 這樣寫的好處是:加大clear標簽的優(yōu)先權(quán)不容易被覆蓋;該0的是0,該是塊元素的必須是塊元素等強制設(shè)定,能增加穩(wěn)定性,對付更多的復雜結(jié)構(gòu)。
缺點1:在每個容器底部添加空元素,會增加代碼的數(shù)量
缺點2(或許值得討論):在IE6下出現(xiàn)容器高損壞現(xiàn)象(這情況似乎未見其他人發(fā)生過,難道一直都是我代碼有錯?)。 圖片展示1:
IE6和IE7都會有此問題。
[?]但在IE7下無法從 效果展示2 中看到,因為本頁滿足了某個“
要求”。在IE6中,可以用鼠標滾輪(或者拉動滾動條)把這個頁面由上滾(拉)到下,再由下滾(拉)回 效果展示2 部分以看到。
更詳細的例子請點擊這里:
IE6/IE7的高屬性破壞現(xiàn)象。
這個問題我稱之為broken height in IE6(或者早就有人用其它名字命名過了),解決方法就是在容器中設(shè)置 height和width不得同時為"auto"或"inherit"之一等。
背景圖不為空:指“url()”括號內(nèi)必須有一個字符,哪怕隨便寫一個,但這樣不合情理。請大家有需要地選擇設(shè)置 height 或 背景色 或 背景圖。
»具體請看:
避免高屬性破壞(broken)的CSS屬性設(shè)置(NEW)。
處理后也可以在IE6中通行了,請看效果展示3。
效果展示3:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。height:1% 這是個clear:both的空元素,為了看得出來,我還是了加點修飾。
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的? 這是個clear:both的空元素,為了看得出來,我還是了加點修飾。
總結(jié):綜上所述,在容器底部添加一個clear過的空元素可以很好的實現(xiàn)CSS浮動清除,只是在IE6中卻要對容器進行一個很小的修改,只差一步就實現(xiàn)零耦合了。而且需要為了IE6進行兩頭設(shè)置,畢竟是不太方便,而方法三就干脆直接修改容器了。請繼續(xù)看 方法三。
方法三(可行):使用偽類 :after
用下面的 代碼展示2 建立一個 clearfix 樣式,并把它添加到容器的class中。
方法出處:
Easyclearing.html代碼展示2:
.clearfix:after {content: ".";display: block;height: 0;clear: both;visibility: hidden;}.clearfix {display: inline-block;}/* Hides from IE-mac \*/* html .clearfix {height: 1%;}.clearfix {display: block;}/* End hide from IE-mac */效果展示4:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。class="clearfix"
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?class="clearfix"
class="clearfix"
正如W3C標準規(guī)范所述,如果想清除浮動,我們是不得不在容器的最后或虛(本方法)或?qū)崳ǚ椒ǘ┑靥砑右粋€clear為 both 的元素。
這個方法對容器的處理很巧妙,但使用的hack比較多。我不喜歡hack,在非逼于無奈的情況下是不會去hack的,所以我之前一直用 方法二,但現(xiàn)在我更喜歡靈活運用。
方法四(有爭議):容器的overflow為auto或hidden?
效果展示5:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。overflow:auto;
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?overflow:hidden;
overflow:auto;
這是傳說中的新方法,可在我的IE6中,卻得到了 完全相反 的效果——浮動溢出! 圖片展示2:
你在IE6下看到的 效果展示5 會像上圖(圖片展示2)那樣出現(xiàn)“浮動溢出”嗎?
能,我相信,因為 容器1 和 容器2 的寬度為auto時IE6是不起作用的,具體請看回:
浮動溢出的條件。
除了這些條件,在我僅能得到的Firefox2、Firefox3b4/b5及IE7中就沒有其它問題。
詳細演示不推薦使用此方法。 除了此方法在IE6下沒效果外,還會導致另外一些問題,請看aoao的
慎用 overflow。
方法五(太片面):overflow為auto/hidden/scroll,關(guān)鍵是width:100%?!
該方法與 方法四 相似,也是為窗口設(shè)置overflow一個值(必須為auto/hidden/scroll當中的一個),只是說:關(guān)鍵在于,要把容器的寬度設(shè)為100%。 效果展示6:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。overflow:auto; width:100%;
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?overflow:hidden; width:100%;
overflow:auto; width:100%;
有人稱這是世界上最簡單的清除浮動方法,而我認為這方法太片面了,而且根本就不是“方法”。
對width值的設(shè)定只是一個IE6下出現(xiàn)浮動溢出的
條件之一。
width設(shè)為100%才行,那我的400px就不行了?而且100%后,padding怎么辦,margin怎么辦,border怎么辦?思考太不全面了。 圖片展示3:
方法六(驚人發(fā)現(xiàn)?):float設(shè)置為left或right!
效果展示7:
這是一個float:left的層,正常來說,它會向外溢出它接觸到的父層。本層嵌套于 容器1
這是一個普通的“靜態(tài)”層,沒有任何與float相關(guān)的設(shè)定,叫 容器1。float:left; width:390px;
本層嵌套于容器2,設(shè)置了float:right。
這個層叫 容器2,與 容器1 區(qū)別不大,不同之處是設(shè)置了clear:both,以及上下margin都為60px。大家量一量,這里的上下margin是以哪個元素為參照的?float:left; width:390px;
float:left;
還有比這更“驚人”的發(fā)現(xiàn)么?
我們清除浮動的目的,是為了讓容器能達到這樣一個要求:即使在子層元素出現(xiàn)浮動的情況下,高度仍然能與子層同步擴展拉長,不會出現(xiàn)子層元素溢出到外部的現(xiàn)象。
[?]我這里的“清除浮動的目的”,如果追究起來是不嚴緊的,因為,就最顯而易見的來說:當子元素的position為absolute時,子元素可以任意的飄。所以對這句“目的”,大家姑且簡單的認為,上面只設(shè)置了浮動(float)與否,不要想太多。(或者想太多的是我自己。)
正如開篇言:清除浮動,我們要輕手輕腳地進行,盡量不要對容器有太多的干擾,這也是清除浮動的原因之一。被處理的容器是 height是auto,這也是元素的默認值,只要這樣才出現(xiàn)高度自動拉伸的需要;相反,如果對容器的高度進行了設(shè)定,或者用JavaScript對元素 高度進行控制,就不是我們要尋找的方法了。
但是,假如我們找的不是這樣一個“CSS清除浮動”方法,而是為了實現(xiàn)目的,那么我們就可以
靈活運用列出的
浮動溢出的條件了。
你的新發(fā)現(xiàn)?
基于我的視野與經(jīng)驗,似乎找不到其它完全獨立于上面的新方法了,其中有很多所謂的新發(fā)現(xiàn)其實只不是過“浮動溢出條件”中的一些影子而已,萬變不離其宗。
如果你有新發(fā)現(xiàn),請與我分享。
再者,脫離了結(jié)構(gòu)的CSS幾乎不能存活,以我的理解是:凡事皆有一度,適可而止也。請看“最佳方法”。
清除浮動最佳方法
CSS清除浮動,就像天下間沒有十全十美的人,也沒有萬能的機器一樣——沒有完美的解決清除方法,也沒有一應(yīng)萬全的解決方案,要實現(xiàn)零耦合已經(jīng)不可能了。
所謂團結(jié)就是力量,如果我們合理地交替地使用一些可行方法,如 方法二 和 方法三,再加上對
浮動溢出的條件的運用,我們在頁面制作中就不會成為單邊撇子了。
jQuery的作者似乎也準備把浮動清除問題也考慮進jQuery。
怎么靈活運用法呢?請看
討論結(jié)果!