層級: 中級 Michael Russell (MikeRussell@VickiFox.com), 系統架構師, Vicki Fox Productions, Inc. 2008 年 4 月 22 日
CSS 浮動屬性(float)是 Web 設計人員工具箱中的一種用來進行頁面配置的常見工具,但瀏覽器實現的不一致性常常會導致該屬性不能被很好的理解和使用。 本文將重點介紹此浮動屬性及其使用、所涉及到的開發工具以及瀏覽器的不一致性問題。
從人類開始書寫文字的早期,我們就看到了文繞圖的實踐。 Web 的先驅們很早就認識到了文字繞圖編排的美學價值及這樣做所能節省出來的空間,於是在 Netscape 1.0 和 HTML 2.0 中都包括進了一種 “浮動” (float)功能。浮動功能亦成為了 HTML 標準和階層式樣式表(Cascading Style Sheet,CSS)規範的基本屬性。 雖然 “浮動” 屬性的定義十分直觀,但該屬性的實現和使用卻讓很多 Web 頁面設計者為了能讓頁面按理想的那樣顯示而煞費苦心並投入了大量的時間。 在本文中,我將介紹 “浮動” 屬性的如下方面:
- 定義和概念性模型
- 常見用例
- 開發工具的問題
- 瀏覽器問題
何為 “浮動” 屬性? 在 CSS2 規範中,可以找到浮動屬性的權威性定義和行為原則。在本文後續的章節中,我將對 CSS2 規範中的 9.5 節 “Visual Formatting Model” 中描述的內容展開討論(相關連結,請參看 參考資料)。 定義 浮動屬性指定了某個框應該向左側還是向右側浮動。此屬性可應用於任何能產生位置不絕對固定的框(box)的元素。 此屬性可有如下的值:
- inherit - 該元素繼承封裝元素的浮動屬性。此值為預設值。
- left - 該元素產生一個浮動到左側的塊狀框。內容排列到該框的右側,並從頂部開始。這種排列取決於元素的 “clear” 屬性。除非該值為 “none”,否則都會忽略 “display” 屬性。
- right - 這種排列取決於元素的 “clear” 屬性。除非該值為 “none”,否則都會忽略 “display” 屬性。
- none - 該框不浮動。
行為 浮動屬性受限於如下規則。本文中,我只對左浮動行為進行詳細描述。要獲得右浮動行為的相應資訊,只需互換方向即可(即,將左換成右)。 此規範依據框的邊框定義行為。CSS 框模型中的四種不同的邊框描述如下:
- content edge 或 inner edge 圍繞所呈現的元素內容。這是最接近內容的邊緣。
- padding edge 包括了應用到某元素的留白。padding edge 定義了此包含塊的邊緣。
- border edge 包括了應用到某元素的邊界。
- margin edge 或 outer edge 包括了應用到某元素的邊框。
包含塊的水平限制:左浮動框的 margin edge 不能在包含塊的左 padding edge 框的左邊。 包含塊的垂直限制:左浮動框的上 margin edge 不能高於包含塊的上 padding edge。 之前浮動限制:如果當前框是左浮動框而且之前的框也是左浮動框,那麼當前框的左 margin edge 必須在之前框的右 margin edge 的右邊,或者當前框的上 margin edge 必須要低於之前框的下 margin edge。 無交疊限制:左浮動框的右 margin edge 不能在任何共用相同水平空間的右浮動框的左 margin edge 之右。 之前元素的垂直限制:左浮動框的上 margin edge 不能高於任何塊或在由來源文件中前一元素產生的被浮動框的上 margin edge。 Line-box 垂直限制:左浮動框的上 margin edge 不能高於任何包含由來源文件中前一元素產生的框的 line-box 的上 padding edge。line-box 是一個假想的矩形框,包含在此塊級包含元素內連成一線的所有 inline box。其高度(上 padding edge)取最高的那個 line-box 的高度。 對立水平邊框限制:如果一個左浮動框的左邊還有另一個左浮動框,那麼這個左浮動框的右 margin edge 不能在此包含塊的右 padding edge 之右。即,左浮動框不能超出此包含塊的右邊緣,除非它已經被定位在向左足夠遠的地方。 最佳垂直限制:浮動框必須被置於此包含塊內盡量高的地方。 最佳水平限制:浮動框必須被置於此包含塊內向左盡量遠的地方。 位置優先原則:在判斷浮動框位置時,最佳垂直限制優於最佳水平限制。即,要先向上移動浮動框,然後再向一側移動。 圖 1 展示了這些行為原則是如何定位一個邊框與文字區塊相關的映像的。 圖 1. 左浮動框的定位樣本
其他考慮 讓 Web 設計新手感到疑惑的一個問題是應該將被浮動元素置於來源文件的什麼位置。要解決這個問題,可以採用如下這些經驗指導。 定位:瀏覽器決定了被浮動元素相對於該元素在文檔的 “正常排列” 中的位置的垂直位置。正常排列是指如果瀏覽器忽略定位屬性的話文檔將如何顯示。被浮動元素會從這種編排被拿出並會被在其包含塊內向左(或右)移動盡量遠的位置。 內聯成為塊:為了頁面格式化,被浮動元素成為了塊狀框。這等價於指定 display: block 屬性。 所需寬度:被浮動元素應該有指定的寬度。CSS2 規範要求元素必須要麼具有使用 “寬度” 屬性指定的顯式寬度,要麼具有從所包含的子項目(比像)計算得出的隱式寬度。映像的隱式寬度是映像屬性的一部分。如果不指定寬度,那麼結果將不可預知。
何為 “clear” 屬性? 被浮動元素的後續元素均會圍繞該被浮動元素。總的來說,對於文本,這是一種所希望出現的效果。但是,如果是為了布局而使用浮動,那麼就需要停止圍繞行為。要停止此行為,後續元素需要指定 “clear” 屬性。 CSS2 規範提供了有關 clear 屬性的權威性定義和行為原則。在本文的後續章節,我將就 CSS2 規範 9.5 節 “ Visual Formatting Model” 展開討論(參見 參考資料)。 定義 clear 屬性工作表明了一個元素的框的哪一側或哪些側不必與之前的浮動框相鄰。如果元素本身具有浮動後代,那麼 clear 屬性對這些後代沒有任何影響。 clear 屬性只能應用於區塊層級元素。這包括藉助浮動屬性被轉變成區塊層級元素的那些元素。 此屬性可以有以下這些值:
- inherit - 此元素承繼封裝元素的 clear 屬性,為預設值。
- left - 增加所產生框的上邊框,以便上 border edge 處於由之前的源元素所產生的任一左浮動框的底 margin edge 之下。
- right - 增加所產生框的上邊框,以便上 border edge 處於由之前的源元素所產生的任一右浮動框的底 margin edge 之下。
- both - 將所產生框移動到由之前的來源文件所產生的所有浮動框之下。
- none - 不對框的位置應用任何與之前的被浮動元素相關的限制。
行為 clear 屬性的行為基本上就是對定位被浮動元素的規則的修改。在此規範中,行為亦被視為一種額外的限制。 Clear 限制:浮動框的上 margin edge 必須要處在所有先前的左浮動框(“clear:left” 的情況)、或所有先前的右浮動框(“clear:right” 的情況)、或二者(“clear:both” 的情況)的底 margin edge 之下。 圖 2 給出了一個 clear 屬性的使用樣本。兩個段落均具有屬性 “clear:left”。這對第一個段落或在第一個段落內定義的浮動框沒有任何影響。clear 屬性只會讓第二個段落定位於浮動之下。請注意第二個段落的上邊框是如何垂直擴充以便與前一段落的底邊框相接的。 圖 2. Clear 定位樣本
其他考慮 與 clear 屬性相關的一個常見困難是其使用常常需要在文檔內的後續元素上添加額外的標記。 清單 1 顯示了添加一個空白的 division 導致向 HTML 文檔增加了非內容標記。 清單 1. 處理 clear 需要額外標記
<div class="myFloatClass"> <p>myFloatClass has float:left specified</p></div><div class="myClearClass" /> <!--myClearClass has clear:left specified--> |
先後有幾名作者提出了各種技術來消除對 HTML 文檔添加額外標記的需要。這些技術包括:
- 向容器元素添加 “float”。
- 向容器元素添加 “overflow:hidden”。
- 在容器元素上添加一個 CSS2 “:after” 偽類。
浮動容器技術(Float Container Technique):該技巧常常見於頁面配置和水平導覽功能表 — 在浮動容器內放上一個浮動元素。浮動容器會被擴大以包含所有內部的浮動元素。這種方式需要準確設定容器的寬度屬性,100% 是常見的一種設定。 這種技術有幾個缺點。第一個缺點是很難設定寬度,使用 100% 可能會與留白衝突。第二,Internet Explorer V6 可能還會添加額外的底邊框。最後,浮動框的深度嵌套常常會導致在瀏覽器中產生某些不可預知的行為。 清單 2 顯示了這種浮動容器技術所使用的 CSS 代碼。 清單 2. 浮動容器技術
.myFloatClass { float: left; width: 100%;} |
隱藏溢出容器技術(Hidden Overflow Container Technique):這種方式很少使用。它涉及了對 “overflow” 屬性和預設的 “clip” 屬性的利用 — 一個溢出 元素會被擴至所有所含子項目(包含被浮動元素)的大小。 這種技術也有幾個缺點。首先,使用溢出可能會影響容器的 fluid height。其次,溢出需要觸發 Internet Explorer V6 的 “hasLayout” 屬性。 清單 3 顯示了隱藏溢出容器技術所使用的 CSS 代碼: 清單 3. 隱藏溢出容器技術
.myFloatClass { overflow: hidden; height: 1%; /* Or zoom:1 to trigger IE's hasLayout */} |
|
分析這篇文章……
|
|
提交到 Digg |
|
|
發布到 del.icio.us |
|
|
Slashdot 一下! |
|
|
|
:after 偽類技術:這種方式極少使用。它所涉及的是使用 CSS 偽類在容器後產生內容。使用 :after 偽類技術向結果 HTML 文檔追加已指定 clear 屬性的新元素。 這種技術最不推崇,提供支援的瀏覽器也少。Internet Explorer V7 或更早的版本不支援 :after 偽類技術。但最為重要的是,這種技術會將無意義的內容插入到結果 HTML 文檔。 清單 4 顯示了 :after 偽類技術所使用的 CSS 代碼。 清單 4. :after 偽類技術
.myFloatClass { height: 1%; /* Or zoom:1 to trigger IE's hasLayout */}.myFloatClass:after { content: "."; display: block; height: 0; clear: both; visibility: hidden;} |
|
“浮動” 有哪些應用? 浮動屬性是 Web 設計者工具箱中的常用工具。其應用的數量之多遠遠超出了設計人員的想象。如下只是浮動屬性的幾個常見應用。 參考資料 部分列出了提供有關如何使用浮動來獲得預期效果的書籍和網站。 錨定映像:將映像移動到左邊或右邊僅僅是部分功能。由於浮動只在元素包括在來源文件內的位置處才有效,所以浮動就在該點設錨。這對於文字文件十分重要,因為在這類文檔內,常常需要讓映像與描述該映像的文本保持位置相對。 添加標題:通常,如能為映像添加標題就更為理想了,比如為映像加上 “Figure 1 Example image”。通過將映像放置於另一個容器內,比如一個分塊 (<div>) 並浮動這個分塊,就可以為映像添加標題。 超大的大寫字母:可以重新建立一種古典書籍樣式,即在一塊文本的左上方放置一個字型較大的大寫字母。但不能只更改字型大小,因為這樣的話,字母上下均會高出其他文本。相反,您所想要的是該字母向下伸展進文本,其餘文本圍繞此字母。 Inline list:浮動和顯示的組合,內聯用來將無序列表 (<ul>) 轉變成水平菜單或導航選項卡。通過用無序列表表示菜單,菜單就會在不能呈現進階或圖形化布局的 網頁瀏覽器(比如只顯示文本的瀏覽器)上顯示為一組選項列表。 多欄頁面配置:使用表來在頁面上進行多欄布局通常都會導致頁面極難維護,因為在來源文件中存在太多的對內容無用的標記。隨著相容 Web 標準的瀏覽器的發展,使用 division 和 CSS 可獲得同樣的布局效果,而所需的原始碼中的標記卻少很多。浮動屬性讓 division 塊獲得了與表儲存格同等重要的地位。 靈活的圖片庫頁面:傳統意義上,表一般會用來布局圖片。表的問題在於它們不是流體,而且當使用者縮放視窗時,也不能很好地響應。通過使用浮動映像,圖片庫雖看起來像表布局,但隨著使用者縮放視窗,布局也會隨之變窄或變寬。比如,在一個靈活性很好的圖片頁面上顯示 12 個圖片,有可能就會有如下的顯示組合:1x12、2x6、3x4、4x3、6x2 和 12x1。 |
|
有無開發工具的考慮? 每個開發人員都知道,並不是所有的 HTML/CSS WYSIWYG 編輯器都是一樣的。每個編輯器都有其自身的特點、對 Web 標準的遵從程度和對頁面呈現引擎的選擇。 我對流行的 WYSIWYG 編輯器(比如 IBM Rational Software Architect V7、Adobe Dreamweaver CS3 和 Genuitec MyEclipse V6)的使用經驗是它們往往對頁面的初始準備很有協助,但若要進行頁面調整和最佳化,您通常都會不得不進行原始碼層級的工作。在目標瀏覽器中進行頁面測試至關重要。很多編輯器都包括了對各種瀏覽器的外掛程式支援,這樣一來,就可以從編輯器中啟動瀏覽器來對頁面進行測試。 如果需要對某個 WYSIWYG 編輯器進行評估,我建議用 Acid2 Browser Test 對此編輯器(參見 參考資料)進行測試。Acid2 Browser Test 由 Web Standards Project 開發,用來測試各種瀏覽器對 Web 標準相容性。不過,您也可以使用 Acid2 Browser Test 源來測試您備選的 HTML/CSS WYSIWYG 編輯器對 Web 標準相容性。 有無瀏覽器方面的考慮? Web 設計人員業已發現了流行的 網頁瀏覽器中的很多非標準的行為。 各種瀏覽器都以不同的方式實現了嵌套浮動元素。其結果是,為了定位的目的,常常需要避免使用被浮動元素的深層嵌套。 在這些情況下,更好的方法是使用相對和絕對位置屬性。 Internet Explorer:Position Is Everything 網站維護 Internet Explorer bug 以及修複手段的目錄。請參看 Explorer Exposed 頁。 Firefox:我在 Firefox 中發現的一個與定位相關的 bug 是 Top Gap Bug。這個 bug 通常都會出現於多欄布局,其中欄是浮動的,而 header section 卻不是。如果其中某個欄中的某個元素具有上邊框,那麼此邊框會被推至 header 之上,導致視窗頂部和 header 頂部之間出現間隙。修複的手段是在被浮動欄上放一些東西。一種方式是向具有 clear:both 屬性的頭的底部添加一個元素。另一種方式是讓 header 也浮動。 Opera:Position Is Everything 網站存有 Opera bug 以及修複手段的目錄。請參看 Opera Omnibus 頁。 結束語 自 網頁瀏覽器技術出現的早期,在頁面上浮動元素的功能就已經存在。現代的 Web 設計開始越來越多地使用浮動屬性來獲得之前使用表實現的頁面配置。儘管浮動屬性的定義和行為都很簡單,但瀏覽器的不一致性卻讓使用此屬性變得有些困難。本文只對浮動屬性作了十分淺顯的介紹。更多資訊,請參看 參考資料 部分,當然,也要勇於親自實踐。 參考資料 |