前端精選文摘:那些年我們一起清除過的浮動

來源:互聯網
上載者:User

一、清除浮動還是閉合浮動?

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

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

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

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

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

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

二、為何要閉合浮動?

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

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

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

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

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

三、閉合浮動的原理

  瞭解 hasLayout 和 BFC(Block Formatting Contexts)。先看一下清理浮動的各種方法:

  1)添加額外標籤

  這是在學校老師就告訴我們的 一種方法,通過在浮動元素末尾添加一個空的標籤例如 <div style=”clear:both”></div>,其他標籤br等亦可。

<div class="warp" id="float1">
<h2>1)添加額外標籤</h2>
<div class="main left">.main{float:left;}</div>
<div class="side left">.side{float:right;}</div>
<div   優雅的 Demo

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

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

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

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

<div class="warp" id="float2">
<h2>2)使用 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="warp" id="float3"   優雅的 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;}  /* for IE/Mac */   </style> <!--[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

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

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

  通過對比,我們不難發現,其實以上列舉的方法,無非有兩類:

  其一,通過在浮動元素的末尾添加一個空元素,設定 clear:both屬性,after虛擬元素其實也是通過 content 在元素的後面產生了內容為一個點的區塊層級元素;

  其二,通過設定父元素 overflow 或者display:table 屬性來閉合浮動,我們來探討一下這裡面的原理。

  在CSS2.1裡面有一個很重要的概念,但是國內的技術部落格介紹到的比較少,那就是 Block Formatting Contexts(塊級格式化上下文),以下簡稱 BFC。

  CSS3裡面對這個規範做了改動,稱之為:flow root,並且對觸發條件進行了進一步說明。

  那麼如何觸發BFC呢?

  1、float 除了none以外的值

  2、overflow 除了visible 以外的值(hidden,auto,scroll )

  3、display (table-cell,table-caption,inline-block)

  4、position(absolute,fixed)

  5、fieldset元素

  需要注意的是,display:table 本身並不會建立BFC,但是它會產生匿名框(anonymous boxes),而匿名框中的display:table-cell可以建立新的BFC,換句話說,觸發塊級格式化內容相關的是匿名框,而不是display:table。所以通過display:table和display:table-cell建立的BFC效果是不一樣的。

  fieldset 元素在www.w3.org裡目前沒有任何有關這個觸發行為的資訊,直到HTML5標準裡才出現。有些瀏覽器bugs(Webkit,Mozilla)提到過這個觸發行為,但是沒有任何官方聲明。實際上,即使fieldset在大多數的瀏覽器上都能建立新的塊級格式化上下文,開發人員也不應該把這當做是理所當然的。CSS 2.1沒有定義哪種屬性適用於表單控制項,也沒有定義如何使用CSS來給它們添加樣式。使用者代理程式可能會給這些屬性應用CSS屬性,建議開發人員們把這種支援當做實驗性質的,更高版本的CSS可能會進一步規範這個。

  BFC的特性:

  1) 塊級格式化上下文會阻止外邊距疊加

  當兩個相鄰的塊框在同一個塊級格式化上下文中時,它們之間垂直方向的外邊距會發生疊加。換句話說,如果這兩個相鄰的塊框不屬於同一個塊級格式化上下文,那麼它們的外邊距就不會疊加。

  2) 塊級格式化上下文不會重疊浮動元素

  根據規定,一個塊級格式化內容相關的邊框不能和它裡面的元素的外邊距重疊。這就意味著瀏覽器將會給塊級格式化上下文建立隱式的外邊距來阻止它和浮動元素的外邊距疊加。由於這個原因,當給一個挨著浮動的塊級格式化上下文添加負的外邊距時將會不起作用(Webkit和IE6在這點上有一個問題——可以看這個測試案例)。

  3) 塊級格式化上下文通常可以包含浮動

  詳見: W3C CSS2.1 - 10.6.7 'Auto' heights for block formatting context roots

  通俗地來說:建立了 BFC的元素就是一個獨立的盒子,裡面的子項目不會在布局上影響外面的元素,反之亦然,同時BFC任然屬於文檔中的普通流。

  至此,您或許明白了為什麼 overflow:hidden或者auto可以閉合浮動了,真是因為父元素建立了新的BFC。對於張鑫旭在對《overflow與zoom”清除浮動”的一些認識 》一文中對於用包裹來解釋閉合浮動的原理,我覺得是不夠嚴謹的,而且沒有依據。並且說道“Firefox等瀏覽器並沒有haslayout的概念”,那麼現代瀏覽器是有BFC的,從表現上來說,hasLayout 可以等同於 BFC。

  IE6-7的顯示引擎使用的是一個稱為布局(layout)的內部概念,由於這個顯示引擎自身存在很多的缺陷,直接導致了IE6-7的很多顯示bug。當我們說一個元素“得到 layout”,或者說一個元素“擁有 layout” 的時候,我們的意思是指它的微軟專有屬性 hasLayout http://msdn.microsoft.com/works... 為此被設為了 true 。IE6-7使用布局的概念來控制元素的尺寸和定位,那些擁有布局(have layout)的元素負責本身及其子項目的尺寸設定和定位。如果一個元素的 hasLayout 為false,那麼它的尺寸和位置由最近擁有布局的祖先元素控制。

  觸發hasLayout的條件:

  position: absolute

  float: left|right

  display: inline-block

  width: 除 “auto” 外的任意值

  height: 除 “auto” 外的任意值 (例如很多人閉合浮動會用到 height: 1% )

  zoom: 除 “normal” 外的任意值 (MSDN) http://msdn.microsoft.com/worksh ... properties/zoom.asp

  writing-mode: tb-rl (MSDN) http://msdn.microsoft.com/worksh ... ies/writingmode.asp

  在 IE7 中,overflow 也變成了一個 layout 觸發器:

  overflow: hidden|scroll|auto ( 這個屬性在IE之前版本中沒有觸發 layout 的功能。 )

  overflow-x|-y: hidden|scroll|auto (CSS3 盒模型中的屬性,尚未得到瀏覽器的廣泛支援。他們在之前IE版本中同樣沒有觸發 layout 的功能)

  hasLayout更詳細的解釋請參見 old9翻譯的 大名鼎鼎的 《On having layout》一文(英文原文:http://www.satzansatz.de/cssd/onhavinglayout.htm),由於old9部落格被牆,中文版地址:

  IE8使用了全新的渲染引擎,刪除了 hasLayout 原本的功能,因此徹底杜絕了很多深惡痛絕的 bug,但 IE8~IE11 通過「document.documentElement.currentStyle.hasLayout」依然可以獲得 hasLayout 的標誌,我寫了一個測試 Demo(IE8 中 zoom:1 返回 false),更詳細的請看《IE8 haslayout = true》

  在不支援 BFC的瀏覽器 (IE6-7),通過觸發 hasLayout 閉合浮動。

四、閉合浮動方法——精益求精

  上面已經列舉了7種閉合浮動的方法,通過第三節分析的原理,我們發現其實更多的:display:table-cell,display:inline-block等只要觸發了BFC的屬性值都可以閉合浮動。從各個方面比較,after虛擬元素閉合浮動無疑是相對比較好的解決方案了,下面詳細說說該方法。

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

  1) display:block 使產生的元素以區塊層級元素顯示,佔滿剩餘空間;

  2) height:0 避免產生內容破壞原有布局的高度。

  3) visibility:hidden 使產生的內容不可見,並允許可能被產生內容蓋住的內容可以進行點擊和互動;

  4)通過 content:"."產生內容作為最後一個元素,至於content裡面是點還是其他都是可以的,例如oocss裡面就有經典的content:"XXXXXXXXX",有些版本可能content 裡面內容為空白,一絲冰涼是不推薦這樣做的,firefox直到7.0 content:”" 仍然會產生額外的空隙;

  5)zoom:1 觸發IE hasLayout。

  通過分析發現,除了clear:both用來閉合浮動的,其他代碼無非都是為了隱藏掉content產生的內容,這也就是其他版本的閉合浮動為什麼會有font-size:0,line-height:0。

  精益求精方案一:

  相對於空標籤閉合浮動的方法代碼似乎還是有些冗餘,通過查詢發現Unicode字元裡有一個“零寬度空格”,也就是U+200B ,這個字元本身是不可見的,所以我們完全可以省略掉 visibility:hidden了

.clearfix:after {content:"\200B"; display:block; height:0; clear:both; }
.clearfix { *zoom:1; }.
  精益求精方案二:

  由 Nicolas Gallagher 大濕提出來的,原文:A new micro clearfix hack,該方法也不存在firefox中空隙的問題。

/* For modern browsers */
.cf:before,.cf:after {
content:"";
display:table;
}
.cf:after { clear:both; }/* For IE 6/7 (trigger hasLayout) */
.cf { zoom:1; }
  需要注意的是:

  上面的方法用到了 :before 虛擬元素,很多人對這個有些迷惑,到底我什麼時候需要用 before 呢?為什麼方案一沒有呢?其實它是用來處理 margin 邊距重疊的,由於內部元素 float 建立了BFC,導致內部元素的margin-top和 上一個盒子的 margin-bottom 發生疊加。如果這不是你所希望的,那麼就可以加上 before,如果只是單純的閉合浮動,after 就夠了!並不是如同大漠《Clear Float》一文所說的:但只使用 clearfix:after 時在跨瀏覽器安全色問題會存在一個垂直邊距疊加的bug,這不是 Bug,是 BFC 應該有的特性。

請看優雅的Demo

  進一步瞭解請看: 《clearfix改良及overflow:hidden詳解【譯】》

  在實際開發中,改進方案一由於存在Unicode字元不適合內嵌CSS的GB2312編碼的頁面,使用方式情節7完全可以解決我們的需求了,改進方案二等待大家的進一步實踐。方案3、4通過overflow閉合浮動,實際上已經建立了新的 塊級格式化上下文,這將導致其布局和相對於浮動的行為等發生一系列的變化,閉合浮動只不過是一系列變化中的一個作用而已。

  所以為了閉合浮動去改變全域特性,這是不明智的,帶來的風險就是一系列的 Bug,比如 Firefox 早期版本產生 focus,截斷絕對位置的層等等。始終要明白,如果單單只是需要閉合浮動,overflow就不要使用,而不是某些文章所說的“慎用”。
  前前後後花了三天寫完了這篇文章。如果覺得本文對您有協助,您的留言就是對我最大的支援,同時由於精力有限,歡迎指出文中錯誤與不足,共勉之!

  參考資料:
  • Page breaks and block-formatting contexts: Allowed page breaks (13.3.3)
  • Clearfix and block formatting contexts: Everything you Know about Clearfix is Wrong
  • Block formating contexts, “hasLayout” – IE Window vs CSS2.1 browsers: simulations.
  • New block formatting contexts next to floats
  • Control Block Formatting Context
  • On having layout  
  • “HasLayout” Overview
  • hasLayout Property
  • IE hasLayout
  • https://developer.mozilla.org/en/CSS/block_formatting_context
您可能感興趣的相關文章
  • 創意無限!一組網頁側邊欄過渡動畫【附源碼下載】
  • 真是好東西!13種非常動感的頁面載入動畫效果
  • 你見過嗎?9款超炫的複選框(Checkbox)效果
  • Magic CSS3 – 協助你實現神奇的互動動畫效果
  • 超贊!基於 Bootstrap 的響應式的後台系統管理範本

 

原文來自:前端精選文摘:那些年我們一起清除過的浮動

編譯來源:夢想天空 ◆ 關注前端開發技術 ◆ 分享網頁設計資源

本文出處【http://www.cnblogs.com/lhb25/】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.