你是否碰到過這種情況:兩個 div
都是 fixed
定位隘冲,但 z-index
值小的反而可以蓋在 z-index
值大的上面蝶溶。
position:fixed 和 z-index
首先明確以下兩個屬性:
1鹅心、position:fixed;
根據(jù) MDN 文檔上的說法
fixed
元素會被移出正常文檔流储狭,并不為元素預留空間级历,而是通過指定元素相對于屏幕視口(viewport)的位置來指定元素位置释移。元素的位置在屏幕滾動時不會改變。打印時寥殖,元素會出現(xiàn)在的每頁的固定位置玩讳。fixed
屬性會創(chuàng)建新的層疊上下文涩蜘。當元素祖先的transform
,perspective
或filter
屬性非none
時,容器由視口改為該祖先熏纯。
2同诫、z-index
只在定位元素上有效,即 position
的值不為 static
時豆巨,而且 z-index
的值越大剩辟,元素的位置越靠前。
參考鏈接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/z-index
所以當我們在一個 div
上使用 position:fixed
時往扔,只要把 z-index
的值設置得越大贩猎,顯示出來時就越靠前(不被遮擋)。
以上就是我在此之前的理解萍膛。
不一樣的情況出現(xiàn)了
今天碰到了這種情況吭服,兩個 div
都是 fixed
定位,但是一個 z-index:21;
的元素蝗罗,把一個 z-index:1001;
的元素給擋住了艇棕。
代碼:
<!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>
.a {
width: 100vw;
height: 100vh;
}
.b {
position: relative;
z-index: 20;
width: 100%;
height: 70%;
background-color: antiquewhite;
}
.c {
position: fixed;
z-index: 1001;
left: 30%;
top: 30%;
width: 30%;
height: 30%;
background-color: aquamarine;
}
.d {
position: fixed;
z-index: 21;
width: 30%;
height: 30%;
left: 40%;
top: 40%;
background-color: red;
}
</style>
</head>
<body>
<div class="a">
<div class="b">
b ---- z-index: 20;
<div class="c">c ---- z-index: 1001;</div>
</div>
</div>
<div class="d">d ---- z-index: 21;</div>
</body>
</html>
效果:
a 包含 b,b 包含 c串塑,而 d 與 a 同級沼琉,c 和 d 都設置 position: fixed;
其中 c 的 z-index 為1001,而 d 的 z-index 為21桩匪,原本期望的結果是 c 在 d 的上面打瘪,如下圖所示:
而實際運行出來的結果是 d 在 c 的上面。
分析原因
經(jīng)過分析傻昙,問題出在 b 上面闺骚,在 b 上面設置了屬性 position: relative;
和 z-index: 20;
,當設置了這兩個屬性之后妆档,在 b 上面就會創(chuàng)建一個層疊上下文僻爽,而 c 又是 b 的子元素,所以即使在 c 上面設置 z-index:1001;
贾惦,它也只是在 b 以內有效胸梆,超出 b 元素范圍后,c 的 z-index 值是沒有意義的纤虽;
b 元素的 z-index
值為20乳绕,它的參考對象是根元素 <html>
,d 的 z-index
值為21逼纸,參考對象也是根元素 <html>
洋措,所以 d 會覆蓋在 b 上面,而 c 又是 b 的子元素杰刽,無法突破 b菠发,所以 c 也只能被 d 覆蓋王滤。
層疊上下文
產(chǎn)生上面這個問題的根本原因就是層疊上下文,所以弄清楚層疊上下文才是關鍵滓鸠,請先仔細閱讀 MDN 上的文檔:層疊上下文雁乡。
在我們使用 z-index
屬性時,一定要考慮層疊上下文糜俗,要清楚當前元素設置 z-index
之后踱稍,究竟是在哪個層疊上下文中起作用的,換句話說就是以哪個元素作參考的悠抹。
產(chǎn)生層疊上下文的條件有十幾種珠月,文檔中的元素只要滿足其中一個,就會在當前元素(起名叫 father)上形成層疊上下文楔敌,而 father 元素的所有子元素啤挎,如果設置了 z-index
,它們在渲染時卵凑,參考的就是 father 元素庆聘,誰的 z-index
值大,誰就在前面勺卢,但即使給這些子元素設置的 z-index
值再高伙判,當超出 father 元素之后,他們的 z-index
就沒有用了黑忱,因為這些子元素和其它元素已經(jīng)不在一個層級上了澳腹。至于能不能顯示在前面,就要看 father 元素的 z-index
了杨何。
可以拿中國的省、地級市沥邻、直轄市來類比:
重慶是一個直轄市危虱,在行政地位與江蘇省同級,而蘇州只是江蘇省下面的一個地級市唐全,假如蘇州市2020年的GDP超過了重慶市(都是假如埃跷,不要抬杠),在江蘇省內開會的時候邮利,蘇州可以排在最前面弥雹,但是如果開全國性的會議時,重慶可以和江蘇省坐一排延届,而蘇州只能坐在后面剪勿,因為級別不同。
這里全國就好比是 <html>
根元素方庭,江蘇省是一個層疊上下文厕吉,重慶也是一個上下文酱固,GDP 就像是 z-index
值。江蘇省和重慶在同一個層級中头朱,都是省級行政單位运悲,而蘇州只是江蘇省這個層疊上下文中的一個子元素,即使蘇州的 GDP 超過了重慶项钮,也還是一個地級市班眯。
搞清楚層疊上下文,在安排元素顯示層級時特別有用烁巫,還能避免一起意料之外的情況發(fā)生署隘,你就能明白,為什么 Element-UI 中有些組件程拭,比如 Dialog定踱、Drawer 這類彈框組件,會有一個 append-to-body
屬性來解決層級問題恃鞋。