1. 程式人生 > >深入理解css中的position定位和z-index屬性

深入理解css中的position定位和z-index屬性

注:本文僅供交流使用,如有不當之處歡迎批評指正,但請註明詳由,謝謝!

由於平時不太用到,所以過去寫css的時候對於position屬性的absolute、relative值理解比較模糊,對於z-index的層疊更是摸不著頭腦,除了理解的因素外,各個瀏覽器的不同解析結果也是一個大問題。今天仔細閱讀了一下css文件,總算是對盒模型的浮動、定位有了比較深刻的理解。

[color=red]我們在實踐中很有可能遇到這樣的問題:[/color]
1、做一個橫向導航,然後滑鼠經過之後出現下拉選單,那麼這個下拉選單的位置控制就是一個關鍵;
2、我們想在一個正常的頁面佈局中放入幾個浮在頁面上的氣泡提示,這時既不想讓氣泡提示破壞正常的文件佈局,又不想氣泡提示的定位在不同的瀏覽器中到處亂飄。
3、當我們在一句正常的文字中插入一個小圖示的話,一般會使用<img />標籤,而這時它的垂直居中問題又是讓人困惑,無論你使用html屬性absmiddle、或是使用css屬性vertical-align、抑或是使用父物件的heigh + line-height,在不同的瀏覽器中總會看起來不同。

嗯,上面幾個問題你是否也遇到過呢?如果你至今還沒有一個很好的解決辦法,不妨繼續閱讀此文,或許能對你有所幫助:)

我們先看一下position屬性的幾個取值定義:
[color=red]position: static、absolute、relative[/color]

static : 預設值。如果沒有指定position屬性,支援position屬性的html物件都是預設為static,可以這麼理解:把html頁面看作一個文件流,原始碼中各個標籤的先後位置就是它們所對應的物件的呈現次序,所有取值為static的物件都按照你所編寫的html標籤的順序依次呈現。
如下圖所示,這是一個常見的指定了float:left;的橫向導航:


relative: 相對定位。這個屬性值保持物件所在文件流中的位置,也就是說它具有和static相同的呈現方式,它同樣佔有在文件流中的固定位置,後面的物件不會侵佔或覆蓋;與static屬性值不同的是,設定了relative的物件,可以通過top, left, right, bottom屬性設定自己的新顯示位置,這4個屬性的取值是相對於文件流的前一個物件的,你可以自由設定這4個屬性偏移到新的位置而不對文件流中的其他物件產生任何影響,原來的頁面呈現仍然會我行我素:


absolute: 絕對定位。和relative不同的是,這個屬性值會將當前物件拖出文件流,後面的物件會佔有原來的位置,也就是說,當前物件的呈現是獨立顯示的,但是它的位置在指定top, left, right, bottom任一屬性之前仍是有繼承性的,這時的4個屬性的取值是相對於瀏覽器的,和文件流無關了。如果把示例中的B區域設定為absolute而不指定4個位置屬性,通過設定margin來改變它的相對位置,用這個方法可以解決前面提到的問題2。


提示a: 蘇昱的css2.0手冊中提到relative和absolute定位的滾動條區別不是絕對的,至少在firefox、opera和safari中滾動條該出現還是會出現。

提示b: 屬性值為absolute物件的z-index屬性可以設定層疊顯示的次序,它是直接有效的;
而屬性值為relative物件的z-index屬性在設定時要小心,把當前物件的z-index設定為-1是不行的,在firefox中它會無法顯示(注意,不是說瀏覽器有誤,而是指如果父物件是根元素body,那麼z-index是無效的,任何z-index設定都不會顯示在根元素之後,除了IE的解析bug,感謝#19提示),必須設定為0以上,我們如果想讓別的物件擋住它,只有將其他物件也設定position為relative,並將z-index屬性取一個比它大的值即可。

上面的表述不知道也許不是很清晰,具體的理解還是要自己親自動手操作一下。

這樣看來,前面的問題就有解了,問題3我們可以根據設計的要求將其設定為相對或絕對定位;
問題1的解決方法也有很多,個人推薦使用有語義的dl, dt, dd來實現,而且這個方法在不同瀏覽器中的表現基本相同(已在ie, firefox, opera, safari中測試),僅在top的屬性上有幾畫素的差異,由於時間關係我只能給出自己測試時的程式碼以供參考:

body {
color:#fff;
font-size:12px;
}
ul li {
float:left;
height:30px;
background-color:#99CC99;
margin:0 10px;
padding:0;
border:1px solid #c30;
width:100px;
}
ul li div {
border:1px solid #f00;
background-color:#996666;
width:100px;
height:100px;
position:absolute;
margin-top:15px;
margin-left:-1px;
*margin-left:-79px;
}
ul li dl,
ul li dl dt,
ul li dl dd {
margin:0;
padding:0;
}
ul li dl dd {
border:1px solid #f00;
background-color:#996666;
width:100px;
height:100px;
position:absolute;
margin-top:11px;
*margin-top:10px;
margin-left:-1px;
}
<ul>
<li>
標題 - #text
<div>
下拉選單 - div
</div>
</li>
<li style="position:relative;">列表b</li>
<li>列表c</li>
<li>
<dl>
<dt>標題 - dt</dt>
<dd>下拉選單 - dd</dd>
</dl>
</li>
</ul>


補充一個例子,請在IE和非IE瀏覽器中對比觀看:
<style>
.main {
width:500px;
height:500px;
background-color:#9cf;
}
.layer_a,
.layer_b,
.layer_c,
.layer_d {
position:absolute;
width:100px;
height:60px;
}
.layer_a {
background-color:#69c;
}
.layer_b {
background-color:#369;
}
.layer_c {
background-color:#eee;
}
.layer_d {
background-color:#696;
}
.brd {
border:1px solid #c30;
margin:1em;
}
.block {
display:block;
}
</style>
<div class="main">
<div class="brd">一段文字一段文字一段文字一段文字一段文字一段文字一段文字<div class="layer_a"></div></div>

<div class="brd">另一段文字另一段文字另一段文字<div class="layer_b"></div></div>
<p class="brd">第三段不同的文字第三段不同的文字<div class="layer_c"></div></p>
<p class="brd block">第四段指定了block的文字<div class="layer_d"></div></p>
<a href="" class="brd">第四段指定了block的文字<div class="layer_c"></div></a>
<map class="brd block">第四段指定了block的文字<div class="layer_d"></div></map>
<dd class="brd">第四段指定了block的文字<div class="layer_a"></div></dd>
<li class="brd">第四段指定了block的文字<div class="layer_b"></div></li>

</div>


從這個例子可以看出,IE將一個塊元素絕對定位時,如果父元素是一個塊級元素,那麼拖出文件流之後它仍會繼承原來所在位置的座標;
而非IE瀏覽器的做法是:拖出文件流之後,直接定位到父元素所在的座標。

[u][color=red]z-index 屬性簡介[/color]

z-index : auto | number
auto: 預設值。
number: 無單位的整數值,可為負數 。

z-index 值較大的元素將疊加在 z-index 值較小的元素之上。對於未指定此屬性的定位物件,z-index 值為正數的物件會在其之上,而 z-index 值為負數的物件在其之下。

注意:這個屬性不會作用於視窗控制元件,如 select 物件。在IE5.5+中, iframe 物件開始支援此屬性。而在之前的瀏覽器版本中, iframe 物件是視窗控制元件,會忽略此屬性。

z-index 屬性適用於定位元素(position 屬性值為 relative 或 absolute 或 fixed的物件),用來確定定位元素在垂直於顯示屏方向(稱為Z 軸)上的層疊順序(stack order)。

每一個定位元素都歸屬於一個stacking context。根元素形成 root stacking context,而其他的 stacking context 則由定位元素產生(此定位元素的 z-index 被定義一個非 auto 的 z-index 值),定位子元素會以這個 local stacking context 為參考,用相同的規則來決定層疊順序。並且 stacking context 和 containing block 之間並沒有必然聯絡。

當 stacking context 一樣的時候,就用 z-index 的值來決定怎樣顯示,如果 z-index 也相同(即 stack level 相同),則按照檔中後來者居上的原則(back-to-front )的順序來層疊。

當任何一個元素層疊另一個包含在不同 stacking context 元素時,則會以 stacking context 的層疊級別(stack level)來決定顯示的先後情況。也就是說,在相同的 stacking context 下才會用 z-index 來決定先後,不同時則由 stacking context 的 z-index 來決定。例如:

定位元素 A(z-index:100)裡面有定位元素 A1(z-index:300),而定位元素 B 和元素 A 兄弟關係(z-index:200)。你會發現無論 A1 的 z-index 是多大,也會被 z-index 是 200 的 B 所覆蓋,因為 A 的 z-index 只有 100。[/u]