第二章 可視化格式模型

 

要掌握的三個最重要的CSS概念是浮動、定位和框模型。這些概念控制在頁面上安排和顯示元素的方式,形成CSS的基本佈局。如果你習慣於用表格控制佈局,那麼這些概念初看上去可能有點兒奇怪。實際上,大多數人只有在使用CSS開發站點一段時間之後,才能完全掌握框模型的複雜性、絕對定位和相對定位之間的差異以及浮動和清理的實際工作方式。在切實掌握這些概念之後,使用CSS開發站點就會變得容易多了。

在本章中,你將學習:

  • 框模型的複雜性和特性。
  • 如何以及爲什麼使用空白邊疊加。
  • 絕對定位和相對定位之間的差異。
  • 浮動和清理是如何工作的。

2.1 框模型概述

框模型是CSS的基石之一,它指定元素如何顯示以及(在某種程度上)如何相互交互。頁面上的每個元素被看做一個矩形框,這個框由元素的內容、填充、邊框和空白邊組成(見圖2-1)。
填充出現在內容區域的周圍。如果在元素上添加背景,那麼背景會應用於由內容和填充組成的區域。因此,常常使用填充在內容周圍創建一個隔離帶,使內容不會與背景混在一起。添加邊框會在填充的區域外邊加一條線。這些線可以有多種樣式,比如實線、虛線或點線。在邊框外邊是空白邊。空白邊是透明的。一般使用它控制元素之間的間隔。

填充、邊框和空白邊都是可選的,默認值爲零。但是,許多元素將由用戶代理樣式設置空白邊和填充。可以通過將元素的 margin 或 padding 設置爲零來覆蓋這些瀏覽器樣式。這可以分別進行,也可以使用通用選擇器對所有元素進行設置:
* {
margin: 0;
padding: 0;
}
在CSS中,width 和 height 指的是內容區域的寬度和高度。增加填充、邊框和空白邊不會影響內容區域的尺寸,但是會增加元素框的總尺寸。假設框的每個邊上有 10 像素的空白邊和 5 像素的填充,如果如果希望這個框達到 100 像素寬,就需要將內容的寬度設置爲 70 像素 (見圖 2-2):

#myBox {

margin: 10px;

padding: 5px;

width: 70px;

}

填充、邊框和空白邊可以應用於一個元素的所有邊,也可以應用於單獨的邊。空白邊還可以是負值,並且在多種技術中都要使用負值的空白邊。

2.1.1 IE/Win 和框模型

不幸的是,IE 5.x 和 IE 6 在怪異模式中使用自己的非標準框模型。這些瀏覽器的 width 屬性不是內容的寬度,而是內容、填充和邊框的寬度總和。這實際上有一定的意義,因爲在現實世界中框具有固定的尺寸,而且填充是放在框裏面的。添加的填充越多,給內容留下的空間就越少。儘管符合邏輯,但是這些 IE 版本不符合規範,這會造成嚴重的問題。例如,在前面的示例中,在 IE 5.x 中框的總寬度只有 90 像素。這是因爲 IE 5.x 認爲 每個邊上 5 像素的填充是 70 像素的寬度的一部分,而不是在寬度之外附加的 (見圖 2-3)。

幸運的是,有幾個方法快可以解決這個問題,這些方法的細節可以在第 9 章中找到。但是,目前最好的解決方案是迴避這個問題。也就是,不要給元素添加具有指定寬度的填充,而是嘗試將填充或空白邊添加到元素的父元素或子元素。

2.1.2 空白邊疊加

空白邊疊加是一個相當簡單的概念。但是,在實踐中對網頁進行佈局時,它會造成許多混淆。簡單地說,當兩個垂直空白邊相遇時,它們將形成一個空白邊。這個空白邊的高度等於兩個發生疊加的空白邊的高度中的較大者。

當一個元素出現在另一個元素上面時,第一個元素的底空白邊與第二個元素的頂空白邊發生疊加 (見圖 2-4)。

當一個元素包含在另一個元素中時候 (假設沒有填充或邊框將空白邊分隔開),它們的頂和/或底空白邊也發生疊加(見圖 2-5)。
儘管初看上去有點兒奇怪,但是空白邊甚至可以與本身發生疊加。假設有一個空元素,它有空白邊,但是沒有邊框或填充。在這種情況下,頂空白邊與底空白邊就碰到了一起,它們會發生疊加 (見圖 2-6) 。
如果這個空白邊碰到另一個元素的空白邊,它還會發生疊加 (見圖 2-7)。

這就是一系列空的段落元素佔用的空間非常小的原因,因爲它們的所有空白邊都疊加到一起,形成一個小的空白邊。

空白邊疊加初看上去可能有點兒奇怪,但是它實際上是有意義的。以由幾個段落組成的典型文本頁面爲例 (見圖 2-8)。第一個段落上面的空間等於段落的頂空白邊。如果沒有空白邊疊加,後續所有段落之間的空白邊將是相鄰頂空白邊和底空白邊的和。這意味着段落之間的空間是頁面頂部的兩倍。如果發生空白邊疊加,段落之間的頂空白邊和底空白邊疊加在一起,這樣各處的距離就一致了。

*****只有普通文檔流中塊框的垂直空白邊纔會發生空白邊疊加。行內框浮動框絕對定位框之間的空白邊不會疊加。*****

2.2 定位概述

既然已經熟悉了框模型,我們就來看看視覺格式化模型定位模型。理解這兩個模型的細微差異是非常重要的,因爲它們一起控制着如何在頁面上佈置每個元素。

2.2.1 視覺格式化模型

p、h1 或 div 等元素常常稱爲塊級元素。這意味着這些元素顯示爲一塊內容,即 "塊框"。與之相反,strong 和 span 等元素稱爲行內元素,因爲它們的內容顯示在行中,即 "行內框"。

可以使用 display 屬性改變生成的框的類型。這意味着,通過將 display 屬性設置爲 block,可以讓行內元素 (比如錨) 表現得像塊級元素一樣。還可以通過將 display 屬性設置爲 none ,讓生成的元素根本沒有框。這樣,這個框及其所有內容就不顯示,不佔用文檔中的空間。

****CSS 中有三種基本的定位機制:普通流、浮動和絕對定位。****

除非專門指定,否則所有框都在普通流中定位。顧名思義,普通流中元素框的位置由元素在 (X)HTML 中的位置決定。

塊級框從上到下一個接一個地排列;框之間的垂直距離由框的垂直空白邊計算出來。

行內框在一行中水平佈置。****可以使用水平填充、邊框和空白邊調整它們的水平間距 (見圖2-9) 。但是,垂直填充、邊框和空白邊不影響行內框的高度。****由一行形成的水平框稱爲行框****行框的高度總是足以容納它包含的所有行內框。但是,設置行高可以增加這個框的高度。****

框可以按照 (X)HTML 元素的嵌套方式包含其他框。大多數框由顯示定義的元素形成。但是,在一種情況下,即使沒有進行顯示定義,也會創建塊級元素。這種情況發生在將一些文本添加到一個塊級元素 (比如 div) 的開頭時。即使沒有把這些文本定義爲段落,它也會被當作段落對待:

在這種情況下,這個框稱爲無名塊框,因爲它不與專門定義的元素相關聯。

塊級元素內的文本行也會發生類似的情況。假設有一個包含三行文本的段落。每行文本形成一個無名行框。無法直接對無名塊或行框應用樣式,因爲沒有可以應用樣式的地方。但是,這有助於理解在屏幕上看到的所有東西都形成某種框。

2.2.2 相對定位

相對定位是一個非常容易掌握的概念。如果對一個元素進行相對定位,它將出現在它所在的位置上。然後,可以通過設置垂直或水平位置,讓這個元素 "相對於" 它的起點進行移動。如果 top 設置爲 20 像素,那麼框將出現在原位置頂部下面 20 像素的地方。如果將 left 設置爲 20 像素,那麼會在元素左邊創建 20 像素的空間,也就是將元素向右移動 (見圖 2-10) 。

在使用相對定位時,無論是否進行移動,元素仍然佔據原來的空間。因此,移動元素會導致它覆蓋其他框。

2.2.3 絕對定位

相對定位實際上被看作普通流定位模型的一部分,因爲元素的位置相對於它在普通流中的位置。與之相反,絕對定位使元素的位置與文檔流無關,因爲不佔據空間。普通文檔流中其他元素的佈局就像絕對定位的元素不存在時一樣 (見圖 2-11) 。

絕對定位的元素的位置相對於最近的已定位祖先元素。如果元素沒有已定位的祖先元素,那麼它的位置相對於最初的包含塊。根據用戶代理的不同,最初的包含塊可能是畫布或HTML 元素。

與相對定位的框一樣,絕對定位的框可以從它的包含塊向上、下、左、右移動。這提供了很大的靈活性。可以直接將元素定位在頁面上的任何位置。

對於定位的主要問題是要記住每種定位的意義。相對定位是 "相對於" 元素在文檔流中的初始位置,而絕對定位是 "相對於" 最近的已定位祖先元素,如果不存在已定位的祖先元素,那麼是最初的包含塊。

因爲絕對定位的框與文檔流無關,所以它們可以覆蓋頁面上的其他元素。可以通過設置 z-index 屬性來控制這些框的堆放次序。z-index 值越高,框在堆中的位置就越高。

絕對定位的元素的位置相對於最近的已定位祖先元素,這使我們能夠實現一些非常有意思的效果。例如,假如希望讓一個文本段落對準一個大框的右下角。只需對包含框進行相對定位,然後相對於這個框對段落進行絕對定位:

#branding {

width: 700px;

height: 100px;

position: relative;

}

#branding .tel {

position: absolute;

right: 10px;

bottom: 10px;

text-align: right;

}

<div id="branding">

<p class="tel">Tel: 0845 838 6163</p>

</div>

相對於相對定位的祖先元素對框進行絕對定位,這在大多數現代瀏覽器中實現得很好。

*****但是,在 Windows 上的 IE5.5 和 IE6 中有一個 bug。如果試圖相對於相對定位的框的右邊或底部設置絕對定位的框的位置,那麼需要確保相對定位的框已經設置了尺寸。如果沒有,那麼 IE 會相對於畫布定位這個框。****

在第9章可以進一步瞭解這個 bug 和修復方法。簡單的解決方案是爲相對定位的框設置寬度和高度,從而避免這一問題。

在進行頁面佈局時,絕對定位是非常有用的工具,尤其是在使用相對定位的祖先元素的情況下。完全可能只使用絕對定位創建出整個設計。爲此,這些元素需要具有固定尺寸,這樣就能夠將它們定位在任何地方而不會有重疊的風險。

因爲絕對定位的元素與文檔流無關,所以它們不影響普通流中的框。如果擴大絕對定位的框 (例如,通過增加字號),周圍的框不會重新定位。因此,尺寸的任何改變會導致絕對定位的框產生重疊,從而破壞精心調整過的佈局。

固定定位

固定定位是絕對定位的一個子類別。差別在於固定元素的包含塊是視口。這使我們能夠創建總是出現在窗口中相同位置的浮動元素。這種情況的一個示例可以在 snook.ca 上看到 (見圖 2-12)。博客評論表單採用固定定位,這使它在頁面滾動時一直出現在屏幕上的相同位置。這有助於改進易用性,用戶不必爲了發表評論而一直滾動到頁面底部。

不幸的是,IE6和更低版本不支持固定定位。爲了解決這個問題,Jonathan Snook 使用 JavaScript 在 IE 中重現了這個效果。

2.2.4 浮動

最後一種定位模型是浮動模型。浮動的框可以左右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊緣

****因爲浮動框不在文檔的普通流中,所以文檔的普通流中的塊框表現得就像浮動框不存在一樣。****

如圖 2-13 所示,當把框 1 向右浮動時,它脫離文檔流並且向右移動,直到它的右邊緣碰到包含框的右邊緣。

在圖 2-14 中,當把框 1 向左浮動時,它脫離文檔流並且向左移動,直到它的左邊緣碰到包含框的左邊緣。因爲它不再處於文檔流中,所以它不佔據空間,實際上覆蓋住了框2,使框2從試圖中消失。如果把所有三個框都向左浮動,那麼框 1向左浮動直到碰到包含框,另外兩個框向左浮動直到碰到前一個浮動框。
如果包含塊太窄,無法容納水平排列的三個浮動元素,那麼其他浮動塊向下移動,直到有足夠的空間的地方 (見圖 2-15)。如果浮動元素的高度不同,那麼當它們向下移動時可能會被其他浮動元素 "卡住" 。

行框和清理
浮動框旁邊的行框被縮短,從而給浮動框留出空間,行框圍繞浮動框。實際上,創建浮動框使文本可以圍繞圖像 (見圖2-16)。

要想阻止行框圍繞在浮動框的外邊,需要對這個框應用 clear 。clear 屬性的值可以是 left、right、both 或 none,它表示框的哪些邊不應該挨着浮動框。爲了實現這種效果,在被清理元素的頂空白邊上添加足夠的空間,使元素的頂邊緣垂直下降到浮動框下面 (見圖 2-17) 。

****浮動元素脫離了文檔流,不影響周圍的元素。但是,對元素進行清理實際上爲前面的浮動元素留出了垂直空間。****
這是一個有用的佈局工具,它讓周圍的元素爲浮動元素留出空間。這解決了前面看到的絕對定位的問題,也就是垂直高度的改變不影響周圍的元素,從而破壞了設計。
我們來更詳細地看看浮動和清理。假設有一個圖片,希望讓它浮動到一個文本塊的左邊。希望將這個圖片和文本包含在另一個具有背景顏色和邊框的元素中。你可能會編寫下面這樣的代碼:
.news {
background-color: gray;
border: solid 1px black;
}
.news img {
float: left;
}
.news p {
float: right;
}
<div class="news">
<img src="news-pic.jpg" />
<p>Some text</p>
</div>
但是,因爲浮動元素脫離了文檔流,所以包圍圖片和文本的 div 不佔據空間。如何讓包圍元素在視覺上包圍浮動元素呢?需要在這個元素中的某個地方應用 clear (見圖 2-18)。

不幸的是,沒有現有的元素可以應用清理,所以需要添加一個空元素並且清理它。
.news {
background-color: gray;
border: 1px solid black;
}
.news img {
float: left;
}
.news p {
float: right;
}
.clear {
clear: both;
}
<div class="news">
<img src="news-pic.jpg" />
<p>Some text</p>
<div class="clear"></div>
</div>
這會實現我們希望的效果,但是要添加不必要的代碼。常常有元素可以應用 clear,但是有時候不得不爲了進行佈局而添加無意義的標記。
還可以不對浮動的文本和圖像進行清理,而是選擇對容器 div 進行浮動:
.news {
background-color: gray;
border: solid 1px black;
float: left;
}
.news img {
float: left;
}
.news p {
float: right;
}
<div class="news">
<img src="news-pic.jpg" />
<p>Some text</p>
</div>
這也會產生我們想要的結果。不幸的是,下一個元素會受到這個浮動元素的影響。爲了解決這個問題,有些人選擇對佈局中的幾乎所有東西進行浮動,然後使用適當的有意義 (常常是站點的頁腳) 對這些浮動元素進行清理。這有助於減少或消除不必要的標記。但是,浮動會變得複雜,而且一些老式瀏覽器在處理有許多浮動元素的佈局時有困難。因此,許多人喜歡添加少量的額外標記。
應用值爲 hidden 或 auto 的 overflow 屬性會自動地清理包含的任何浮動元素,而不需要添加額外的標記。這個方法並不適合所有情況,因爲設置框的 overflow 屬性會影響它的表現。
最後,一些人使用 CSS 生成的內容或 JavaScript 對浮動元素進行清理。這兩種方法的基本概念是相同的。並不直接向標記中添加進行清理的元素,而是將它們動態地添加到頁面中。對於這兩種方法,需要指定進行清理的元素出現在哪裏,而且常常需要添加一個類名:
<div class="news clear">
<img src="news-pic.jpg" />
<p>Some text</p>
</div>
在使用 CSS 方法時,結合使用 :after 僞類和內容聲明在指定的現有內容的末尾添加新的內容。在這個示例中,我添加了一個句點,因爲它是個非常小的不引人注意的字符。不希望新的內容佔據垂直空間或者在頁面上顯示,所以需要將 height 設置爲 0,將 visibility 設置爲 hidden 。因爲被清理的元素在它們的頂空白邊上添加了空間,所以生成的內容需要將它的 display 屬性設置爲 block 。
這樣設置之後,就可以對生成的內容進行清理:
.clear:after {
content: ".";
height: 0;
visibility: hidden;
display: block;
clear: both;
}
這個方法在大多數現代瀏覽器中是有效的,但是在 IE6 和更低版本中不起作用。有各種解決方案,其中許多記錄在 www.positioniseverything.net/easyclearing.html 中。最常用的解決方案涉及使用 Holly 招數 (見第8章),從而迫使 IE5-6應用 "佈局" (見第9章) 和不正確地清理浮動元素。
.clear {
display: inline-block;
}
/* Holly Hack Targets IE Win only */
* html .clear { height: 1%; }
.clear {display: block;}
/* End Holly Hack */
但是,由於其複雜性,這個方法可能不適合所有人採用。

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