羅才華
摘 要: 浮動是CSS的基本定位機(jī)制之一,在網(wǎng)頁布局中應(yīng)用非常廣泛。本文對浮動引起的父元素高度坍塌現(xiàn)象進(jìn)行了分析,并提出了clear屬性和觸發(fā)新的BFC兩種清除浮動的方法。實驗結(jié)果表明,在眾多觸發(fā)新的BFC條件中,.clearfix清除浮動的方式在不破壞文檔結(jié)構(gòu)的同時,也沒有增加太多的代碼,在解決瀏覽器兼容性問題方面也表現(xiàn)突出。
關(guān)鍵詞: 浮動; 坍塌; 觸發(fā); BFC; 清除浮動
中圖分類號:TP312 文獻(xiàn)標(biāo)志碼:A 文章編號:1006-8228(2018)10-64-04
Abstract: Float is one of the basic positioning mechanisms of CSS and is widely used in web layout. This paper analyzes the phenomenon of parent element height collapse caused by floating, and proposes two methods to clear floating, which are clear attribute and triggering new BFC. The experimental results show that in many new BFC trigger conditions, the .clearfix does not destroy the structure of the document, and also does not add too much code, so it also does well in solving the problem of browser compatibility.
Key words: floating; collapse; trigger; BFC; clear floating
0 引言
定位(positioning)在基于DIV+CSS的網(wǎng)頁布局中扮演重要角色,CSS中提供了三種基本的定位機(jī)制,即普通流(static)、浮動(float)和絕對(absolute)定位。定位可以指定該元素相對于其正常位置,或者相對于另一個元素、父元素、甚至瀏覽器窗口的位置。利用CSS中的一些屬性,可以創(chuàng)建列式布局,它除了可以實現(xiàn)布局的一部分與另一部分重疊外,還可以代替以前需要使用多個表格才能完成的任務(wù)。
頁面元素的默認(rèn)定位方式是普通流(有時也稱為文檔流)定位。在普通流定位中,頁面中的行內(nèi)元素和塊級元素分別按照從左到右和從上到下順序逐個排列,每個塊級元素獨占一行顯示。如何讓多個塊級元素顯示在同一行?這里就引出了浮動。
1 浮動
在CSS1中首次提出了浮動的概念,它以增加一個功能為基礎(chǔ)。浮動設(shè)計的初衷是用來實現(xiàn)文字環(huán)繞效果,通過將文章中的圖片左右浮動,使圖片下方的文字自動環(huán)繞在圖片周圍,這樣就有效解決了圖片的左邊或者右邊出現(xiàn)一大塊留白的問題。后來人們發(fā)現(xiàn),浮動用來做布局效果非常不錯,甚至有時候都忘了它本是為實現(xiàn)文字環(huán)繞而生。
設(shè)置了浮動的元素不但可以像塊元素那樣設(shè)置其寬高,并且可以做到內(nèi)聯(lián)排列,它介于inline和block之間。在inline-block推出之前,浮動在頁面布局中得到了廣泛的應(yīng)用,在 inline-block推出來以后,浮動的應(yīng)用也隨處可見。
2 浮動的效果
給元素設(shè)置了浮動定位,浮動的框向左或向右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊框為止。另外,由于浮動框脫離了文檔的普通流,所以文檔里普通流中塊框的表現(xiàn)就像浮動框不存在一樣。
如果子元素都向一個方向浮動(如左?。?,而它們的父元素包含框不夠?qū)?,無法容納水平排列的這些浮動子元素時,那么,其他浮動塊將向下移動,直到有足夠的空間,如圖1所示。另外,如果浮動子元素的高度不同,那么當(dāng)它們向下移動時,可能會出現(xiàn)被其他浮動元素“卡住”的現(xiàn)象[1],如圖2所示。
3 浮動對頁面的影響
浮動的元素會脫離文檔的普通流,不再占據(jù)頁面空間,所以會對其父元素高度帶來一定的影響。如果一個元素中所包含的子元素都是浮動元素,并且沒有為該元素設(shè)置高度(該元素的高度由它的內(nèi)容來決定,即父元素高度自適應(yīng)),那么,經(jīng)常會發(fā)生父元素高度坍塌(collapse)的現(xiàn)象[2]。父元素高度坍塌即父元素不能被子元素正常撐開,父元素高度變成0。另外,坍塌可能會對其周圍的布局產(chǎn)生一定的影響,所以清除浮動此時就顯得十分重要。以下圖3和圖4分別為本文示例的html代碼和css代碼。
本例中id為outer的div沒有設(shè)置高度,正常情況下,它的高度會被其子元素?fù)伍_,可是它內(nèi)部的三個子元素p都設(shè)置了左浮動,所以該div發(fā)生了高度坍塌,上下邊界重合。
4 清除浮動
清除浮動的方式有很多種,但是實現(xiàn)的原理主要是依賴clear屬性和觸發(fā)新的BFC(Block formatting context)。
4.1 BFC
格式化上下文(Formatting context)是CSS2.1規(guī)范中提出的一個概念,它規(guī)定了其子元素將如何定位,以及和其他元素間的關(guān)系及相互作用。最常見的格式化上下文有BFC和IFC(Inline formatting context),本文只探討B(tài)FC。
BFC意譯為“塊級格式化上下文”,它表示一個獨立的渲染區(qū)域,是一個隔離了的獨立容器,只有塊級盒子(block-level box)參與,它規(guī)定了內(nèi)部的塊級盒子如何布局,與這個渲染區(qū)域外部無關(guān)[3]。只要某個元素符合成為BFC的條件之一,該元素內(nèi)部子元素的布局和定位就不受其外部元素的影響。實驗表明,當(dāng)把元素的CSS屬性display設(shè)置為block、list-item和table三者之一時,就會生成塊級盒子,并且參與BFC。
4.2 BFC布局規(guī)則
⑴ BFC是一個獨立的渲染區(qū)域和隔離的獨立容器,容器里面的子元素不會影響到外面的元素,反之亦然;
⑵ 當(dāng)元素定位為absolute時,它是可以超出它的包含塊邊界的。而BFC中的子元素則不會超出它的包含塊,每個子元素的左外邊距(margin-left)與其包含塊的左邊界(border-left)相接觸(如果是從右往左格式化,則相反);
⑶ 在BFC中,盒子在垂直方向從包含塊的頂端開始逐個排列,相鄰盒子之間的垂直間隙由他們的margin值決定;
⑷ 處于相同BFC的兩個相鄰塊級盒子垂直外邊距會發(fā)生重疊,且與方向無關(guān),但BFC的區(qū)域不會與浮動元素的區(qū)域發(fā)生重疊;
⑸ BFC是一個獨立的渲染區(qū)域和隔離的獨立容器,容器里面的子元素不會影響到外面的元素,反之亦然;
⑹ 浮動元素的高度參與到BFC的高度計算中。
4.3 觸發(fā)BFC的條件
⑴ 根元素;
⑵ 浮動元素(元素的float屬性取none以外的值,left、right和inherit);
⑶ 元素的overflow屬性取visible以外的值(hidden、auto和scroll );
⑷ 表格單元格 (元素的display屬性取值為table-cell或table-caption);
⑸ 彈性盒(元素的display屬性取值為flex或inline-flex);
⑹ 行內(nèi)塊(元素的display屬性取值為inline-block);
⑺ 元素的position屬性取值為absolute或fixed。
5 清除浮動的幾種方法
5.1 給父元素設(shè)置固定高度
父元素高度沒有被里面的浮動子元素?fù)伍_,這是因為它所有子元素都設(shè)置了浮動,而浮動元素會脫離文檔流,而父元素本身沒有高度,所以我們看到其高度發(fā)生了坍塌[4-5]。此時只需要給該父元素設(shè)置一下高度就可以,但是父元素的高度設(shè)置多少合適呢?這種做法也脫離了本文的目的(網(wǎng)頁設(shè)計者總是希望外層父元素的高度由其里面的內(nèi)容來決定)。
5.2 使用額外標(biāo)簽
W3C標(biāo)準(zhǔn)提議在容器的末尾增加一個空元素(如div,p等),并將該空元素樣式設(shè)置“clear:both”,這樣做相當(dāng)于強(qiáng)迫容器適應(yīng)它的高度,以便裝下所有的浮動元素。Clear屬性的作用是清除當(dāng)前元素由于前面的元素浮動所帶來的影響。如果在id為outer的div元素內(nèi)部的末尾增加一個“clear:both”的div標(biāo)簽,就可以清除浮動,代碼如下:
雖然這種方法能有效解決浮動引起的父元素高度坍塌的問題,但是它存在語義不明確、容易造成HTML結(jié)構(gòu)的混亂、違背HTML結(jié)構(gòu)與CSS表現(xiàn)相分離的思想和增加后期維護(hù)難度等諸多缺點,所以現(xiàn)實中這種用法并不多見。特別是在頁面復(fù)雜的布局中,可能要經(jīng)常清除浮動,用這種方式就會產(chǎn)生很多額外的空標(biāo)簽,不利于頁面結(jié)構(gòu)優(yōu)化。
5.3 使用float屬性
將父元素float屬性值設(shè)置為left/right,可以有效清除浮動。它的優(yōu)點是簡單、代碼量少、基本不存在結(jié)構(gòu)和語義化問題,主要缺點是對后續(xù)元素會有影響,在頁面布局中一般不采用這種方式。
5.4 使用display屬性
將父元素display屬性值設(shè)置為table-caption、table-cell和 inline-block三者之一時,可以有效清除浮動。由于display: inline-block會產(chǎn)生多余空白,在頁面布局中基本不用這種方式。為了保證兼容性,通常用display:table來替代display:table-caption和display:table-cell。值得注意的是,在上面列出的觸發(fā)BFC的條件中沒有出現(xiàn)display:table的身影,事實上display:table觸發(fā)BFC的原因是它會默認(rèn)生成一個匿名的table-cell,從而觸發(fā)了新的BFC,代碼如下:
#outer{ zoom: 1; //解決IE6/7兼容性問題
display: table; width: 100%; }
它的優(yōu)點主要是沒有違背HTML結(jié)構(gòu)與CSS表現(xiàn)相分離的思想、語義化正確和代碼量少,缺點是盒模型屬性發(fā)生了改變,會引起其他問題,因此,這種方法在實際開發(fā)中用的也不是很多。
5.5 使用overflow屬性
將父元素overflow屬性值設(shè)置為hidden、auto或scroll三者之一時,可以有效清除浮動,但如果子元素使用了定位,父元素清除浮動的效果將會受到影響。另外,這種方式不能滿足子元素要溢出顯示的情況(如下拉菜單),因為子元素離開了overflow屬性值為hidden、auto或scroll的父元素所在的區(qū)域以后,會被隱藏或者出現(xiàn)滾動條,因此,這種方式在實際應(yīng)用中也不多見。
值得一提的是,當(dāng)overflow屬性值為hidden時,其語義為“溢出:隱藏”,雖然子元素為浮動,但其仍然處在父元素中,可是父元素此時高度發(fā)生坍塌,子元素就算發(fā)生溢出現(xiàn)象,也應(yīng)該被隱藏起來才對,但此時父元素的高度為什么反而被撐開了呢?這是因為它觸發(fā)了新的BFC,且該BFC不會與浮動的子元素重疊,因此父元素的高度被撐開了。
5.6 使用.clearfix
使用.clearfix來清除浮動元素對父元素的影響,這是目前網(wǎng)站比較流行的清除浮動的方式。具體做法是給父元素定義一個class,一般取值為.clearfix。下面列出三種使用.clearfix清除浮動的方式。
⑴ 只使用單偽元素:after。下面是使用:after這個偽類清除浮動的三種流行寫法:
① clearfix:after{ clear:both; display:block; visibility:
hidden; height:0;content:"."; }
② clearfix:after{ clear:both; display:block; height:0;
content:" \200B"; }
③ clearfix:after { display: table; content: " "; clear:
both;}
在標(biāo)準(zhǔn)瀏覽器下,after偽類會在設(shè)置了.clearfix的元素后面插入一個clear:both的塊元素,因此清除了子元素浮動所帶來的影響。然而IE6/7并不支持:after偽類,為了解決IE6/7的兼容性問題,可以在上面三種代碼的后面加上.clearfix{ zoom:1;//解決IE6/7兼容性問題}。因為zoom: 1將觸發(fā)hasLayout,使元素閉合內(nèi)部的浮動。
偽元素:after與前面提到的空標(biāo)簽閉合浮動的方法相比,優(yōu)點是沒有增加額外的空標(biāo)簽,不破壞文檔結(jié)構(gòu),沒有副作用;缺點是代碼數(shù)量比較多。
⑵ 使用雙偽元素:after和:before。下面是使用:after和:before偽類清除浮動的一種流行寫法:
.clearfix:before,.clearfix:after { display: table; content: ".";}
.clearfix:after{ clear:both; }
.clearfix { zoom: 1; //解決IE6/7兼容性問題}
這里偽元素:before主要用來消除瀏覽器上邊距折疊的影響。
⑶ 只使用.clearfix,既不使用偽元素after,也不使用偽元素before。下面列出只使用.clearfix清除浮動的三種簡單有效的寫法:
① clearfix{ zoom:1; display: table; width: 100%; }
② clearfix{ overflow:hidden;_zoom:1; }
③ clearfix{ overflow:auto;_height:1%; }
6 結(jié)束語
浮動是網(wǎng)頁布局常用的一種定位機(jī)制和手段,本文通過對浮動引起的父元素高度坍塌現(xiàn)象進(jìn)行分析,再結(jié)合筆者的教學(xué)實踐,提出了使用clear屬性和觸發(fā)新的BFC兩種清除浮動的方法。滿足觸發(fā)新的BFC的條件眾多,篇幅所限,本文只列舉了幾種常用方式,并從文檔結(jié)構(gòu)性、代碼復(fù)雜性和結(jié)構(gòu)與表現(xiàn)相分離等方面進(jìn)行了對比分析。實際上,使用.clearfix清除浮動,會增加一些代碼,但在文檔結(jié)構(gòu)性、瀏覽器兼容性和結(jié)構(gòu)與表現(xiàn)相分離等方面都表現(xiàn)優(yōu)異。
參考文獻(xiàn)(References):
[1] CSS浮動-w3school 在線教程[EB/OL]. [2018-05-28]. http://www.w3school.com.cn/css/css_positioning_floating.asp.
[2] 辛紅.CSS層疊樣式表浮動與清除浮動技術(shù)研究[J].現(xiàn)代職業(yè)教育,2017.11.
[3] 劉建東.一種適合多級導(dǎo)航菜單清除浮動的方法[J].通訊世界,2016.17(9):223.
[4] 李剛.瘋狂HTML5 CSS3 JavaScript講義[M].電子工業(yè)出版社,2012.
[5] 徐洪峰.HTML+DIV+CSS網(wǎng)頁設(shè)計與布局實用教程[M].清華大學(xué)出版社,2017.