閱讀本文前,應當對于CSS盒模型以及視覺格式化模型中會產生的各種框(box,也可以成為盒子)以及各種不同的布局方式有比較準確的認識,可以閱讀杜瑤大神的兩篇文章,這兩篇文章也是對標準中相關章節的翻譯和闡述。
(1) 視覺格式化模型中的各種框
(2) 置換和非置換元素
或直接閱讀CSS2.1 SPEC中的相關章節:
(1) Box model
(2) Visual formatting model
在講包含塊之前還是想先簡單說一下視覺格式化模型
1、CSS視覺格式化模型
標準中對于視覺格式化模型的闡述為:
how user agents process the document tree for visual media.
即用戶代理在視覺媒體下如何處理文檔樹,用戶代理最常見的比如瀏覽器,而負責頁面解析和渲染的就是瀏覽器的渲染引擎(現在更多地直接稱為瀏覽器內核),文檔既可以包括HTML文檔,也包括其他通用標記語言所編寫的文檔。在視覺格式化模型中,文檔樹中的每個元素都會根據盒模型產生0個或多個框,影響這個框的布局的因素有:
(1)框的尺寸和類型,比如塊級框和行內級框的布局方式就是不同的。
(2)框的定位方式,display屬性絕對了一個元素所產生的框的定位方式,定位方式不同的框在布局時也有不同的規則。
(3)與其他框的關系,假如有兩個框,它們之間是包含關系還是同輩關系而所產生的布局是不相同的。
(4)其他的額外信息(比如視口的大小,置換元素的固有尺寸等)
從這個角度講,視覺格式化模型就是對上述這些因素是如何影響一個框的布局而進行的詳細描述。
2、視口(viewport)
第一部分中出現了視口這個詞,直觀上看,我覺得視口可以理解為用戶代理用來呈現解析和渲染后的文檔樹的區域,用戶通過這個區域可以閱讀文檔得內容,在瀏覽器中,視口一般就是瀏覽器用于呈現網頁的區域。
標準中對于視口的闡述為:
User agents for continuous media generally offer users a viewport (a window or other viewing area on the screen) through which users consult a document.
注意加粗的continuous media,我們平時所瀏覽的網頁就屬于連續媒體,而通過打印機打印的文檔內容必須是分頁的,所以就是分頁媒體,即paged media(此處的解釋略粗糙,僅是個人的簡單看法)。網頁是連續的媒體,那么問題就來了,視口不可能跟隨網頁的大小而變化,因此視口在小于文檔的尺寸時,必須提供一種滾動機制,最常見的就是瀏覽器的滾動條,通過滾動條我們就可以瀏覽超出視口的文檔部分,也就是文檔中闡述的:
When the viewport is smaller than the area of the canvas on which the document is rendered, the user agent should offer a scrolling mechanism.
當然關于視口的知識點可不只是上述的這么簡單,比如在移動web中,viewport的相關屬性對于移動web的開發至關重要,但本文暫不涉及其他關于視口的知識點。
3、包含塊(containing block)
一個網頁是由一個一個的框(box)所組成的,每一個框在頁面中都有自己的尺寸、位置以及其他的渲染屬性(如背景色,字體等),那么這些框在布局的時候,它們的位置是如何決定的呢?另外,如果沒有為框定義顯示的尺寸(width,padding,border,margin)等,那么它們的尺寸又是如何確定的呢?答案的關鍵點就是包含塊,個人認為,包含塊是學習CSS布局時基礎中的基礎,不過還好,這個概念也并不難理解。
首先看一下標準中對于包含塊的闡述:
The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element.
即視覺格式化模型中所產生的各種框,它們的位置和大小往往都是根據一個特定的矩形框邊緣來計算得到的, 這個矩形框就是這個box的包含塊。
注:如果講一個框的包含塊時,指的是它所處的包含塊,而不是它形成的包含塊。
那么該如何確定一個框的包含塊呢?標準中規定了相應的規則:
3.1根元素的包含塊
根元素(HTML中就是html標簽)的包含塊稱為初始包含塊:對于連續媒體(比如網頁),它具有視口的尺寸并且定位在畫布的原點(可以直觀理解為視口的內容起始位置,如果初始包含塊的direction屬性為ltr,那么起點位置就是視口的左上角,如果為rtl,那么就為視口的右上角)。初始包含塊的direction與根元素的direction屬性相同,默認為ltr,即從左到右。
特別注意:初始包含塊具有視口的尺寸,也就是說寬高都是和視口相同的,即使視口中出現了滾動
3.2元素定位為static(默認值)或relative(相對布局)時的包含塊
對于定位屬性為static(默認值)或relative(相對布局)的元素,其包含塊是由最近的祖先塊容器框的內容區域構成。
這一點也比較好理解,雖然出現了塊容器框和內容區域兩個詞,對于CSS盒模型和視覺格式化模型中的各種框有所了解后應該就能明白。下面有個簡單的例子:
##DEMO 1:static或relative定位的元素的包含塊
CSS代碼:
.container{
width: 1000px;
margin: 50px auto;
border: 2px solid #000000;
padding: 50px;
}
static定位的元素
3.3元素定位為absolute時的包含塊
對于position為absolute的元素,其包含塊為最近的擁有非static定位屬性(即position為relative,absolute或fixed)的元素所產生,有下面兩種情況:
<1>如果這個元素為一個塊容器框元素,那么包含塊由這個元素的內邊距邊界(padding edge)形成
<2>如果這個元素是一個行內元素,那么這個包含塊由包圍該行內級元素的第一個行框和最后一個行框的box形成。如果行內元素被分割成了多行,那么在CSS2.1中,包含塊則是未定義的。
如果沒有這樣的祖先,那么其包含塊就是初始包含塊
注:在分頁媒體中包含不一樣的情況,本文暫不討論分頁媒體中的情況
absolute的情況相對復雜一些,看以下例子:
##DEMO 2:絕對定位元素的包含塊(1)-塊容器框形成包含塊
CSS代碼:
.container{
width: 1000px;
margin: 50px auto;
border: 2px solid #000000;
padding: 50px;
position: relative;
}
.absolute-div-1{
position: absolute;
left: 0px;
top: 0px;
}
absolute定位的元素
效果如下:
##DEMO 3:絕對定位元素的包含塊(2)-行內元素形成包含塊
DEMO3中,我們把container換成行內元素span,為了更明顯地顯示效果,我們給body加了一個高度并且設置了背景色,并且為span和absolute-div-1設置了不同的字體顏色,代碼如下CSS代碼:
body{
margin: 0px;
font-size: 14px;
height: 500px;
background: #a0b3d6;
}
.container{
margin: 50px auto;
position: relative;
color: #eeeeee;
}
.absolute-div-1{
position: absolute;
color: #ff0000;
left: 0px;
top: 0px;
}
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
absolute定位的元素
在IE6/7中效果也相同,另外我們提到過,如果元素是一個行內級元素,那么這個包含塊由包圍該行內級元素的第一個行框和最后一個行框的box形成。我們來驗證標紅部分的闡述,即把absolute-div-1的top定位改為bottom,即bottom:0px,效果如下:
這也驗證了標準中所闡述的內容。
注:在IE6中,絕對定位元素如果只用bottom定位,但是形成包含塊的元素沒有觸發hasLayout時,bottom不會根據包含塊的底部來定位,這個bug通過zoom:1等屬性觸發hasLayout可以解決。
##DEMO 4:絕對定位元素的包含塊(4)-行內元素被分割成多行時
視覺格式化模型中描述過,如果一個行內級元素包含了塊級元素,那么這個行內級元素就會被分割成2塊,并且都成為了塊級元素。我們把DEMO3中的container改動一下:
< span class= "container">
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
中間出來了一個div
absolute定位的元素
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
而chrome中的效果為:
可以看出,chrome中的絕對定位元素在定位時是基于被分割后形成的第二個框來定位的,而如果我們把絕對定位元素移動到分割元素之前,即:
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
absolute定位的元素
中間出來了一個div
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含塊行內級包含
##DEMO 5:絕對定位元素的包含塊(4)-初始包含塊作為包含塊
如果一個絕對定位元素找到有非static定位屬性的祖先,那么初始包含塊就作為其包含塊,這里需要注意的是初始化包含塊的尺寸問題,2.1節中曾經講過初始包含塊具有視口的尺寸,即使存在滾動時,DEMO代碼如下:CSS代碼:為了出現滾動,我們為body加了1000px的高度
.body-for-demo4{
height:1000px;
background: #a0b3d6;
}
.absolute-div-2{
height: 100px;
width: 100px;
background: #03a9f4;
position: absolute;
bottom: 0px;
left:0px;
}
HTML代碼:
如果我們把body設置一個position:relative的屬性,那么絕對定位框就會跑到頁面底部了。
2.4元素定位為fixed時的包含塊
元素定位屬性為fixed時,對于連續媒體,包含塊由視口形成,對于分頁媒體,則由頁面區域形成。
position為fixed的元素特點是不隨頁面的滾動而滾動,它的包含塊由視口形成,這一點也比較好理解。但是IE6不支持fixed的屬性,可以使用css表達式或者hack的方式使IE6支持fixed。可參考:
http://caibaojian.com/468.html
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com