那些年我們一起清除過的浮動

本文純屬轉載,只是部分內容,全文請拜讀原文

前言:本文只轉載原博文部分內容,稍加排版編輯;想要詳細學習,請拜讀原文,感謝一絲冰涼(原文作者),並對原作者花費三天時間來寫這篇博文的做法致已崇高的敬意

article_face

浮動(float),一個我們即愛又恨的屬性。愛,因爲通過浮動,我們能很方便地佈局; 恨,浮動之後遺留下來太多的問題需要解決,特別是IE6-7(以下無特殊說明均指 windows 平臺的 IE瀏覽器)。也許很多人都有這樣的疑問,浮動從何而來?我們爲何要清除浮動?清除浮動的原理是什麼?本文將一步一步地深入剖析其中的奧祕,讓浮動使用起來更加得心應手。

一、清除浮動 還是 閉合浮動 (Enclosing float or Clearing float)?

很多人都已經習慣稱之爲清除浮動,以前我也一直這麼叫着,但是確切地來說是不準確的。我們應該用嚴謹的態度來對待代碼,也能更好地幫助我們理解開頭的三個問題。

1、清除浮動:清除對應的單詞是 clear,對應CSS中的屬性是 clear:left | right | both | none;

2、閉合浮動:更確切的含義是使浮動元素閉合,從而減少浮動帶來的影響。

兩者的區別 請看優雅的 Demo;

通過以上實例發現,其實我們想要達到的效果更確切地說是閉合浮動,而不是單純的清除浮動,在footer上設置clear:both清除浮動並不能解決wrap高度塌陷的問題。

結論:用閉合浮動比清除浮動更加嚴謹,所以後文中統一稱之爲:閉合浮動。

二、爲何要閉合浮動?

要解答這個問題,我們得先說說CSS中的定位機制:普通流,浮動,絕對定位 (其中”position:fixed” 是 “position:absolute” 的一個子類)。

1、普通流:很多人或者文章稱之爲文檔流或者普通文檔流,其實標準里根本就沒有這個詞。如果把文檔流直譯爲英文就是 document flow ,但標準裏只有另一個詞,叫做 普通流 (normal flow),或者稱之爲常規流。但似乎大家更習慣文檔流的稱呼,因爲很多中文翻譯的書就是這麼來的。比如《CSS Mastery》,英文原書中至始至終都只有普通流 normal flow(普通流) 這一詞,從來沒出現過document flow (文檔流)

2、浮動:浮動的框可以左右移動,直至它的外邊緣遇到包含框或者另一個浮動框的邊緣。浮動框不屬於文檔中的普通流,當一個元素浮動之後,不會影響到塊級框的佈局而只會影響內聯框(通常是文本)的排列,文檔中的普通流就會表現得和浮動框不存在一樣,當浮動框高度超出包含框的時候,也就會出現包含框不會自動伸高來閉合浮動元素(“高度塌陷”現象)。顧名思義,就是漂浮於普通流之上,像浮雲一樣,但是隻能左右浮動。

正是因爲浮動的這種特性,導致本屬於普通流中的元素浮動之後,包含框內部由於不存在其他普通流元素了,也就表現出高度爲0(高度塌陷)。在實際佈局中,往往這並不是我們所希望的,所以需要閉合浮動元素,使其包含框表現出正常的高度。

絕對定位就不多說了,不在本文討論範圍之內,下回分解。

三、閉合浮動的原理——瞭解 hasLayout 和 Block formatting contexts

先看一下清理浮動的各種方法

1、添加額外標籤

通過在浮動元素末尾添加一個空的標籤,其他標籤br等亦可

<div class="wrap" id="float1">
    <h2>添加額外標籤</h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
    <div style="clear:both;"></div>
</div>
<div class="footer">.footer</div>

優雅的 Demo

  • 優點:通俗易懂,容易掌握

  • 缺點:可以想象通過此方法,會添加多少無意義的空標籤,有違結構與表現的分離,在後期維護中將是噩夢,這是堅決不能忍受的,所以你看了這篇文章之後還是建議不要用了吧。

2、使用 br標籤和其自身的 html屬性

這個方法有些小衆,br 有 clear=“all | left | right | none” 屬性

<div class="wrap" id="float2">
    <h2>使用 br標籤和其自身的 html屬性</h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
    <br clear="all" />
</div>
<div class="footer">.footer</div>

優雅的 Demo

  • 優點:比空標籤方式語義稍強,代碼量較少

  • 缺點:同樣有違結構與表現的分離,不推薦使用

3、父元素設置 overflow:hidden

通過設置父元素overflow值設置爲hidden;在IE6中還需要觸發 hasLayout ,例如 zoom:1;

<div class="wrap" id="float3" style="overflow:hidden; *zoom:1;">
    <h2>父元素設置 overflow </h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
</div>
<div class="footer">.footer</div>

優雅的 Demo

  • 優點:不存在結構和語義化問題,代碼量極少

  • 缺點:內容增多時候容易造成不會自動換行導致內容被隱藏掉,無法顯示需要溢出的元素;04年POPO就發現overflow:hidden會導致中鍵失效,這是我作爲一個多標籤瀏覽控所不能接受的。所以還是不要使用了

4、父元素設置 overflow:auto 屬性

同樣IE6需要觸發hasLayout,演示和3差不多

  • 優點:不存在結構和語義化問題,代碼量極少

  • 缺點:多個嵌套後,firefox某些情況會造成內容全選;IE中 mouseover 造成寬度改變時會出現最外層模塊有滾動條等,firefox早期版本會無故產生focus等, 請看 嗷嗷的 Demo ,不要使用

5、父元素也設置浮動
  • 優點:不存在結構和語義化問題,代碼量極少

  • 優點:使得與父元素相鄰的元素的佈局會受到影響,不可能一直浮動到body,不推薦使用

6、父元素設置display:table

**優雅的 Demo

  • 優點:結構語義化完全正確,代碼量極少

  • 優點:盒模型屬性已經改變,由此造成的一系列問題,得不償失,不推薦使用

7、使用:after 僞元素

需要注意的是 :after是僞元素(Pseudo-Element),不是僞類(某些CSS手冊裏面稱之爲“僞對象”),很多閉合浮動大全之類的文章都稱之爲僞類,不過csser要嚴謹一點,這是一種態度。

由於IE6-7不支持:after,使用 zoom:1觸發 hasLayout。

該方法源自於: How To Clear Floats Without Structural Markup

原文全部代碼如下:

<style type="text/css">  
.clearfix:after {  
    content: "."; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden;  
}   
.clearfix {
    display: inline-block;
} 
</style> 

/* for IE/Mac */   
<!--[if IE]> 
<style type="text/css"> 
.clearfix {
    zoom: 1;            /* triggers hasLayout */  
    display: block;     /* resets display for IE/Win */
} 
</style>  
<![endif]-->  

鑑於 IE/Mac的市場佔有率極低,我們直接忽略掉,最後精簡的代碼如下:

.clearfix:after {
     content:"."; 
     display:block; 
     height:0; 
     visibility:hidden; 
     clear:both; 
}
.clearfix { 
    *zoom:1; 
}

**優雅的 Demo

  • 優點:結構和語義化完全正確,代碼量居中

  • 優點:複用方式不當會造成代碼量增加

原文結尾:

前前後後花了三天寫完了這篇文章。如果覺得本文對您有幫助,您的留言就是對我最大的支持,同時由於精力有限,歡迎指出文中錯誤與不足,共勉之!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章