前陣子在切版時遇到了較複雜的版型,花費了較多時間在規劃佈局及試錯,希望能藉此文章的整理好好了解 z-index 及 stacking context 的觀念。
為何了解 z-index 及 stacking context 非常重要
元素的重疊在切版中也許不會常常出現,甚至一些排版較單純的專案上是完全不用擔心這一塊的。
然而,如果對其完全沒有認識,很可能就會因為佈局的規劃出錯,導致須花費額外時間來補救。
不知道你是否有這樣經驗:
區塊 A 不知為何蓋過了區塊 B,不論把區塊 B 的 z-index 設到多大都無法讓區塊 B 蓋過區塊 A
藉著了解元素在不同狀況下的堆疊方式,可以有效地減少這類狀況的發生。
在沒有 z-index 時,元素如何決定先後順序?
當未設定 z-index 時,元素會這樣由下到上排序:
- 父層的框線與背景
- 子層未設定 position 的元素依出現順序
- 設定 position 的元素依出現順序
以下例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.wrapper {
padding: 20px;
display: inline-block;
background-color: rgb(199, 199, 0);
}
.box {
height: 200px;
border: 3px solid;
}
.non-positioned-1 {
width: 200px;
background-color: rgba(100, 100, 255, 0.8);
border-color: rgb(0, 0, 255);
}
.non-positioned-2 {
width: 300px;
background-color: rgba(100, 255, 100, 0.8);
border-color: rgb(0, 255, 0);
margin-top: -250px;
}
.positioned-1 {
width: 400px;
position: relative;
margin-top: -100px;
background-color: rgba(200, 50, 50, 0.8);
border-color: rgb(255, 0, 0);
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box non-positioned-1">
<code>non-positioned-1</code>
</div>
<div class="box positioned-1">
<code>positioned-1</code>
</div>
<div class="box non-positioned-2">
<code>non-positioned-2</code>
</div>
</div>
</body>
</html>
父層的 wrapper
會在最下層,而 non-positioned-1
因為在 HTML 中先於同為子層的 non-position-2
,因此被排在下方;positioned-1
儘管先於 non-positioned-2
,因為其設定了 position: relative
被排在最上方。
使用 z-index 改變上下排序
讓我們思考一個情境:如何讓藍綠紅由上到下排序呢?
以往在我的直覺上,我就會試著將 non-positioned-1
的 z-index
設定為10 或是更大,但很顯然在此例中即使設定為 999 依然不會作用。
z-index
用於在 z 軸 (z-axis) 上的位置,預設為 auto,可給予整數作為值,其僅會作用於定位元素 (positioned element) ,因為元素在預設的定位上採用 position: static
來排序,因此 left
, right
, top
, bottom
以及上述的 z-index
均無法作用。
在此例中,只要將三個盒子的 CSS 做一點調整,便能達成上述的情境:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.wrapper {
padding: 20px;
display: inline-block;
background-color: rgb(199, 199, 0);
}
.box {
height: 200px;
border: 3px solid;
}
.positioned-2 {
width: 200px;
background-color: rgba(100, 100, 255, 0.8);
border-color: rgb(0, 0, 255);
position: relative;
z-index: 2;
}
.positioned-3 {
width: 300px;
background-color: rgba(100, 255, 100, 0.8);
border-color: rgb(0, 255, 0);
margin-top: -250px;
position: relative;
z-index: 1;
}
.positioned-1 {
width: 400px;
position: relative;
margin-top: -100px;
background-color: rgba(200, 50, 50, 0.8);
border-color: rgb(255, 0, 0);
z-index: 0;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box positioned-2">
<code>positioned-2</code>
</div>
<div class="box positioned-1">
<code>positioned-1</code>
</div>
<div class="box positioned-3">
<code>positioned-3</code>
</div>
</div>
</body>
</html>
堆疊環境 Stacking Context
堆疊環境(又稱層疊上下文)是指一組擁有共同父層的子元素一起在 z 軸上上下移動。
形成堆疊環境的條件有許多種。以上例來說,當我們將元素的 position
設定為 relative
且給予了 z-index
時,便各自形成了獨立的堆疊環境,其之間便可透過設定 z-index
決定其在 z 軸上的位置。如上例來看:
上面提到堆疊環境是指一組擁有共同父層的子元素一起在 z 軸上上下移動。擁有共同父層意味著什麼呢?讓我們在紅色背景父層的子層中加入一個橘色的子層 div:
// HTML
<div class="box positioned-1">
<code>positioned-1</code>
<div class="positioned-1-child"></div>
</div>
// CSS
.positioned-1-child {
width: 350px;
height: 150px;
background-color: orange;
position: absolute;
bottom: 0;
z-index: 999;
}
此時會發現,即使將子層的 z-index
設定為 999,依然無法讓橘色的盒子在堆疊上超過綠色或藍色的盒子,這是因為其父層的 z-index
為 0。
那要讓橘色的盒子移動到 Z 軸的最上方,可以怎麼做呢?
由於堆疊環境形成的條件之一是 position
為 relative
且給予 z-index
時,只要將 position-1
的 z-index
移除讓其變成預設的 auto,.position-1-child
便會自成一個堆疊環境,藉此達成目的:
.positioned-1 {
width: 400px;
position: relative;
margin-top: -100px;
background-color: rgba(200, 50, 50, 0.8);
border-color: rgb(255, 0, 0);
/* z-index: 0; */
}
.positioned-1-child {
width: 350px;
height: 150px;
background-color: orange;
position: absolute;
bottom: 0;
z-index: 999;
}
關於 z-index 及 stacking-context 就記錄到這,希望這篇文可以幫助到路過的你,如果內容或觀念上有任何錯誤,還請不吝指出,謝謝!
References: