1. 概念
在視覺格式化模型中,文檔樹中的每一個元素都將會根據盒模型產生零到多個盒子。這些盒子的佈局由以下因素決定:
- 盒子的尺寸和類型
- 定位策略(正常文檔流,浮動或者絕對定位)
- 和文檔樹中其餘元素的關係
- 額外的信息(好比視口的大小,圖片的原始尺寸等)
1.1 視口(viewport)
連續媒體(continuous media)的UA(user agent/用戶代理)一般會給用戶提供一個視口,通常爲一個窗口或者屏幕上的一片可視區域。用戶經過這個視口查看文檔(document)。當視口的大小改變時,UA可能會改變文檔的佈局。
當視口的大小比文檔所渲染的區域(畫布,canvas)小時,UA須要提供滾動機制。每一個畫布只能有至多一個視口,可是UA能夠將一個文檔渲染到多個畫布上去(好比提供同一個文檔的不一樣展現方式)。
1.2 包含塊
在CSS2.1中,許多盒子的位置和大小都是根據一個叫作包含塊(containing block)的長方形盒子的邊進行計算的。一般,生成的盒子做爲後代盒子的包含塊,也就是說一個盒子產生它後臺盒子的包含塊。「盒子的包含塊」指的是包含盒子的包含塊,而不是盒子產生的包含塊。
每一個盒子都根據它的包含塊進行定位,但並不會受包含塊限制,它可能溢出(overflow)
2. 控制盒子的生成
下面幾節描述了CSS2.1中可能產生的盒子的類型。在視覺格式化模型中,盒子的類型會部分的影響盒子的行爲。在CSS2.1中,能夠經過"display"屬性指定盒子的類型。
2.1 塊級元素和塊級盒子
塊級元素(Block-level element)就是在那些源文檔中被格式化成可見的塊的元素,好比段落。"display"屬性的以下取值將會把元素變成塊級元素:"block"、"list-item"和"table"。
塊級盒子(Block-level box)就是那些在塊格式化上下文(block formatting context)中的盒子。每一個塊級元素都會產生一個主塊級盒子。這個主塊級盒子包含後代盒子和其餘生成的內容,同時還參與任何的定位策略。有些塊級元素,除了主塊級盒子之外,還將產生其餘的盒子,如"list-item"元素。這些額外的盒子將根據主塊級盒子進行佈局。
除了表盒子和可替代的元素盒子,塊級盒子一般也是塊容器盒子(block container box)。一個塊容器盒子既能夠僅包含塊級盒子,又能夠創建一個行內格式化上下文,從而包含行級盒子。並非全部的塊容器盒子都是塊級盒子,不可替代的行內塊以及不可替代的表格單元都是塊容器盒子,但他們都不是塊級盒子。那些是塊容器盒子的塊級盒子被叫作塊盒子(block box)。
當上下文含義清晰的時候,塊級盒子、塊容器盒子和塊盒子有時被簡稱爲塊。
2.2 行級元素和行內盒子
行級元素就是那些源文檔中不會致使新塊的產生的元素,元素的內容分佈在行內。例如段落的強調文字部分、行內圖片等。"display"屬性的以下屬性值指定一個元素爲行級元素:"inline"、"inline-table"和"inline-block"。行級元素產生行級盒子,這些行級盒子存在於行內格式化上下文中。
一個行級盒子既表如今它是行級的,又表如今它的內容存在於包含他的行內格式化上下文中。設置了"display:inline"的不可替代元素將會產生一個行盒子。不是行盒子的行級盒子(如可替代的行級元素、行內塊元素和行內表格元素)被稱爲原子行級元素,由於這些盒子在他們的行內格式化上下文中表現爲一個單一的不透明盒子。
2.3 "display"屬性
"display"屬性的取值範圍是: inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit
"display"屬性的初始值爲"inline"。
一下是每種取值的具體含義:
- block 應用該屬性值的元素將會產生一個塊盒子。
- inline-block 應用該屬性值的元素將產生一個行級塊容器。inline-block的內部被格式化成一個塊盒子,元素自己被格式化成一個原子行級盒子。
- inline 應用該屬性值的元素將會產生一到多個行盒子。
- list-item 應用該屬性值的元素(好比html中的li)將會產生一個主塊級盒子和一個標籤盒子。
- none 應用該屬性值的元素將不會出如今格式化結構(formatting structure)中,也就是說,元素不產生任何盒子,對佈局沒有任何影響。元素的後代元素也不產生盒子,元素和元素的內容被從格式化結構中徹底刪除。經過設置後代元素的"display"屬性值也不能改變。請注意,"display"爲"none"時不產生任何不可見的盒子,實際上,根本不產生任何盒子。若是想 產生既不可見又影響格式化結構的盒子,請參考visibility屬性。
- table,inline-table,table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, and table-caption;應用以上屬性值的元素將表現得像一個表格元素。
注意,儘管"display"屬性的初始值爲"inline",可是UA的默認樣式表可能覆蓋這個值。
如下是一些display屬性的例子:
p { display: block } em { display: inline } li { display: list-item } img { display: none }
3. 定位策略(Positioning schemes)
在css 2.1中,一個盒子將通過定位策略來進行定位:
- 正常文檔流(Normal flow)。 在CSS2.1中,正常文檔流包括塊級盒子的塊格式化上下文,行級盒子的行格式化上下文以及塊級盒子和行級盒子的相對定位。
- 浮動(Floats)。 在浮動模型中,一個盒子先根據正常文檔流定位,而後被從文檔流中拿出來儘量的放到左/右邊。上下文中的其餘內容將流動到浮動元素的某一邊。
- 絕對定位(Absolute positioning)。 在絕對定位模型中,盒子被從正常文檔流中徹底移除(被移除的盒子對它原來的兄弟盒子將再也不產生任何影響) 而且根據它的包含塊進行定位。
若是一個元素是浮動的、絕對定位的或者是根元素(root element),那麼就稱這個元素脫離了文檔流(out-of-flow)。若是一個元素沒有脫離文檔流,那麼就稱這個元素在文檔流內(in-flow)。一個脫離文檔流的元素A,它的文檔流包括元素A自己以及全部A的在文檔流內的後代元素。
3.1 position 屬性
position屬性的取值範圍是:static | relative | absolute | fixed | inherit, 初始值爲static。每一個取值的含義以下:
- static 應用該屬性值的盒子就是正常的盒子,根據正常的文檔流來進行定位。top、right、bottom和left屬性不生效。
- relative 應用該屬性值的盒子,其位置將根據盒子在正常文檔流中初始的位置以及一個偏移量來計算。即盒子的最終位置將相對於原來的位置發生必定的偏移。當盒子B採用相對定位後,盒子B後面的其餘盒子的定位將不受影響,就好像盒子B沒有采用相對定位同樣。
- absolute 應用該屬性值的盒子,其位置由top、right、bottom和left屬性來決定,這些屬性將根據盒子的包含塊來肯定偏移量。採用絕對定位的盒子徹底脫離正常文檔流,也就是說,絕對定位的盒子對其餘盒子將再也不產生任何影響。採用絕對定位的盒子的外邊距(margin)不與其餘盒子的外邊距重疊(collapse)。
- fixed 應用該屬性值的盒子,其位置將根據絕對定位來計算,另外,盒子還將相對於必定的參照物固定不動。例如在視覺媒體中,採用fixed定位的盒子將相對於視口(viewport)固定不動。
UA可能默認根元素的定位爲static定位。
3.2 盒子的偏移: top、right、bottom、left
若是一個元素的position屬性值不爲static,那麼就稱這個元素被定位了。被定位的元素將產生被定位的盒子,而後根據以下四個屬性進行放置:
top
top屬性的取值範圍是: 絕對長度值 | 百分比 | auto | inherit, 初始值爲auto。
該屬性指定一個絕對定位的盒子的外邊距上邊界(top margin edge)距離這個盒子的包含塊的上邊界(top edge)的偏移量(距離)。對於採用相對定位的盒子來講,這個偏移量根據盒子自己的上邊界計算得出,也就是說,盒子初始採用正常文檔流中的位置,而後在那個位置的基礎上根據該屬性值進行必定的偏移。
right
right屬性的取值範圍是: 絕對長度值 | 百分比 | auto | inherit ,初始值爲auto。
跟top屬性同樣,該屬性指定一個絕對定位的盒子的外邊距右邊界(right margin edge)距離這個盒子的包含塊的右邊界(right edge)的偏移量(距離)。對於採用相對定位的盒子來講,這個偏移量根據盒子自己的右邊界計算得出。
bottom
botton屬性的取值範圍是: 絕對長度值 | 百分比 | auto | inherit, 初始值爲auto。
跟top屬性同樣,該屬性指定一個絕對定位的盒子的外邊距下邊界(bottom margin edge)距離這個盒子的包含塊的下邊界(bottom edge)的偏移量(距離)。對於採用相對定位的盒子來講,這個偏移量根據盒子自己的下邊界計算得出。
left
left屬性的取值範圍是: 絕度長度值 | 百分比 | auto | inherit, 初始值爲auto。
跟top屬性同樣,該屬性指定一個絕對定位的盒子的外邊距左邊界(left margin edge)距離這個盒子的包含塊的左邊界(left edge)的偏移量(距離)。對於採用相對定位的盒子來講,這個偏移量根據盒子自己的左邊界計算得出。
上面這四個屬性的具體取值有以下含義:
- 絕對長度值 相對於參考邊的偏移量是個固定的距離且能夠爲負。
- 百分比 偏移量是盒子包含塊寬度(left、right)或高度(top、bottom)的百分比,能夠爲負。
- auto 自動。
4. 正常文檔流(Normal flow)
在正常文檔流中的盒子都屬於一個格式化上下文(formatting context)。這個格式化上下文既能夠是塊級的,也能夠是行級的,但不能二者都是。塊級盒子在塊格式化上下文(block formatting context)中,行級盒子在行格式化上下文(inline formatting context)中。
4.1 塊格式化上下文
浮動的元素、採用絕對定位的元素、不是塊盒子的塊容器(好比inline-block,table-cell和table-caption)以及設置了overflow且值不爲visible(設置了visible的viewport除外)的塊盒子將會爲他們的內容創建新的塊格式化上下文。
在塊格式化上下文中,各個盒子從他們的包含塊的頂部開始,豎直的順次放置。相鄰的兩個盒子的豎直距離有margin屬性決定。在同一個格式化上下文中的兩個相鄰的塊級盒子的豎直外邊距將會合並。
在塊格式化上下文中,每一個盒子的左外邊界與盒子的包含塊的左邊界相接(對於從右到左的狀況,右外邊界與右邊界相接)。 即便當有浮動元素存在是也依然使用,除非這個盒子產生了新的塊格式化上下文(這樣的話,因爲浮動,盒子的寬度將變小)。
5.浮動
浮動的盒子會被移動到當前行的左邊或者右邊。浮動最有趣的特色就是其餘內容會在浮動的元素的旁邊依次放置(或者經過設置clear屬性禁止),或者說其餘盒子會流動到浮動盒子的旁邊。也就是說,其餘盒子將沿着向左浮動的盒子的右邊、向右浮動的盒子的左邊依次放置。
一個浮動的盒子將會一直向左或向右移動,一直到觸碰到包含塊的邊界或者其餘浮動盒子的外邊界。若是是行盒子的話,那麼浮動盒子的外邊界的頂部將與當前行盒子的頂部對其。
若是沒有足夠的水平空間,那麼浮動的盒子將移至下一行直到有足夠的空間或者行內已經沒有其餘浮動元素爲止。
由於浮動盒子不在文檔流中,因此在浮動盒子先後的未定位的塊盒子將像浮動盒子不存在同樣的豎直依次放置。可是,浮動盒子所在的當前行以及後面相鄰的行盒子都會根據浮動盒子縮短寬度來給浮動盒子留下空間。
若是有個豎直的位置知足以下四個條件: (a)在行盒子的頂部或者頂部之下(b)在行盒子的底部或底部之上(c)在浮動盒子的外邊界的頂部或者頂部之下(d)在浮動盒子的外邊界的底部或者底部之上,那麼行盒子將會換行。也就是說,若是浮動的盒子的外邊界高度爲0或者爲負,那麼行盒子不會縮短。
若是縮短的行盒子過短而不能包含任何內容,那麼這個行盒子將會換行(而且高度會從新計算)直到有足夠的空間或者沒有浮動盒子爲止。當前行內的任何在浮動盒子以前的盒子都將從新流動到浮動盒子的另外一邊。換句話說,若是一個行內盒子放在了一個向左浮動盒子的前面,那麼,向左浮動的盒子將會放在這一行的開始,與行盒子的頂部對其,以前的行內盒子將會移動到浮動盒子的右邊。對於rtl和向右浮動的盒子同理。
table、塊級可替換元素或者正常文檔流中創建新的塊格式化上下文的元素的border盒不能與任何在同一個格式化上下文中的浮動盒子的margin盒重疊。
5.1 float屬性
float屬性的取值範圍是: left | right | none | inherit,初始值爲none。
該屬性值決定元素向左移動仍是向右移,或者根本不動。float屬性能夠被應用於任何元素上,除了絕對定位的元素。float屬性的取值有以下含義:
- left 元素產生一個向左浮動的塊盒子。其餘內容流向盒子的右邊。
- right 與left類似,盒子浮動到右邊,其餘內容流向盒子的左邊。
- none 不浮動
以下9條規定了浮動元素的確切行爲:
- 向左浮動的盒子的外左邊界不能超過包含塊的左邊界。同理應用於向右浮動的盒子。
- 對於一個向左浮動的盒子,若是在這個盒子以前還有其餘向左浮動的盒子,那麼,這個盒子的左外邊界不能超過其餘任何向左浮動的盒子的右外邊界,或者這個盒子的上邊界必須比其餘盒子的下邊界低。同理應用於向右浮動的盒子。
- 任何向左浮動的盒子的右外邊界不能超過任何與之相鄰的向右浮動的盒子的左外邊界。同理應用於向右浮動的盒子。
- 浮動盒子的上外邊界不能比包含塊的上邊界高。當浮動發生在兩個合併的margin中時,浮動的盒子根據一個假設的父的空匿名塊盒子定位。
- 浮動盒子的上外邊界不能比任何其餘以前的塊盒子或浮動盒子的上外邊界高。
- 浮動盒子的上外邊界不能比任何以前的行盒子的上邊界高。
- 一個向左浮動的盒子,若是在他以前還有向左浮動的盒子,那麼這個盒子的右外邊界不能超過包含塊的有邊界,除非這個盒子已經儘量的向左了。同理應用於向右浮動的盒子。
- 浮動元素要儘量的往高放置。
- 向左浮動的盒子要儘量向左,向右浮動的盒子要儘量向右。可是相對於儘量向左或向右,更高的位置有更高的優先級。
下面的html片斷,b浮動到右邊:
<P>a<SPAN style="float: right">b</SPAN></P>
若是P元素的寬度足夠,那麼a和b將各佔一邊,以下:
5.2 clear屬性
clear屬性的取值範圍是: none | left | right | both | inherit, 初始值爲none。只應用於塊級元素。
該屬性決定元素盒子的哪一邊不與浮動盒子相鄰。clear屬性不考慮被應用元素內部的浮動以及其餘塊格式化上下文中的浮動。
屬性取值含義以下:
- left 應用該屬性值的元素盒子的上邊界要低於該元素以前的左浮動元素盒子的底外邊界。
- right 應用該屬性值的元素盒子的上邊界要低於該元素以前的右浮動元素盒子的底外邊界。
- both 應用該屬性值的元素盒子的上邊界要低於該元素以前的左浮動或右浮動元素盒子的底外邊界。
- none 不浮動。
全部不是none的值都將引入空隙(clearance)。clearance禁止margin合併,表現得就像元素的上外邊距外還有一段空間。
要計算應用了clear屬性的元素的clearance,首先須要找到元素上邊界的假定位置。這個假定位置就是當clear屬性值爲none時元素實際上的上邊界。
若是假定的元素的上邊界不能越過相關的浮動元素(past the relevant floats),那麼就須要引入clearance。
空隙的大小爲以下兩個值中的較大值:
- 將元素的上邊界與最低的浮動元素的底外邊界對齊須要的空間大小。
- 將元素的上邊界放置到它假定的位置須要的空間大小。
注意,空隙的大小可能爲負也可能爲0.
6.display、position和float的關係
這三個屬性都影響盒子的產生以及定位,他們關係以下:
- 若是display的值爲none,那麼position和float不起做用。在這種狀況下,元素不產生盒子。
- 不然,若是position的值爲absolute或者fixed,那麼盒子就使用絕對定位,float的最終使用的值爲none,display的取值依據以下表格來定。盒子的顯示位置根據top、right、bottom和left屬性決定。
- 不然,若是float的取值不會none,那麼盒子將會浮動,display的取值參照下表。
- 不然,若是元素是根元素,那麼display的取值參照下表。
- 不然,display的取值就是指定的值。
-
指定的值 |
最終使用的值 |
inline-table |
table |
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block |
blockcss |
其餘 |
與指定的值相同html |