掌握CSS中的z-index
- 2022 年 7 月 21 日
- 筆記
前言
z-index
是一個用於控制文檔中圖層順序的屬性。具有較高z-index
值的元素將會出現在具有較低值的元素之上。就像頁面上的x軸和y軸決定一個元素在水平和垂直方向上的位置一樣,z-index
控制它們在z軸上相互層疊的方式。
默認層疊順序
當我們編寫HTML時,出現在文檔靠後位置的元素,會自然層疊到靠前位置的元素之上。
<body>
<header class="site-header"></header>
<main class="site-content"></main>
<footer class="site-footer"></footer>
</body>
基於上面給定的HTML片段,如果它們的位置相互重疊的話,footer
將會層疊在main
內容區域之上,main
將會層疊在header
之上。
元素可以通過使用position
屬性和偏移屬性的組合來進行重疊,偏移屬性值包括top
,right
,bottom
以及left
。
如果為每個元素設置position: absolute
,他們都會在彼此的基礎上進行布局。footer
元素在文檔中最後出現,因此默認情況下,該元素會層疊在前兩個元素之上。
.site-header, .site-content, .site-footer {
position: absolute;
width: 400px;
padding: 20px;
}
.site-header {top: 0; left: 0;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px;}
如果使用偏移屬性top
和left
,我們可以更清楚地看到層疊順序。
層疊上下文
雖然使用position: absolute
可以創建相互重疊的元素,但我們還沒有創建所謂的層疊上下文。
層疊上下文可以通過以下任意方式進行創建:
- 元素的
position
屬性值為absolute
或者relative
,且z-index
值不為auto
。 flex
容器的子元素,且z-index
值不為auto
。opacity
屬性值小於1
的元素。transform
屬性值不為none
的元素。
到目前為止,最常見的創建和使用層疊上下文的方式是上述列表中的第一種,所以讓我們多花點時間來關注它。
回到先前的示例,我們有三個元素彼此重疊,但目前為止它們並沒有z-index
值。
z-index
屬性允許我們控制層疊的順序。如果在footer
元素上設置z-index: 1
,在main
元素上設置z-index: 2
,以及在header
元素上設置z-index: 3
,那麼默認層疊順序將會完全顛倒。
表面上看起來很簡單,更高的z-index
值有更高的元素層疊順序。因此z-index: 9999
總是位於z-index: 9
上面。事實果真如此嗎?不幸的是,實際情況要更複雜一些。
層疊上下文中的z-index
<header class="site-header blue">header</header>
<main class="site-content green">content
<div class="box yellow"></div>
</main>
<footer class="site-footer pink">footer</footer>
如果我在site-content
容器內添加一個box
,並將其定位在右下角之外,我們可以看到它位於綠色盒子的上面和粉色盒子的下面。
.box {
position: absolute;
bottom: -25px;
right: -25px;
z-index: 4; /* won't work :( */
width: 75px;
height: 75px;
border: 1px solid #000;
}
.site-header {top: 0; left: 0; z-index: -1;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px; z-index: 3;}
基於我們所了解的z-index
,我們可能會認為,為了使這個黃色的盒子出現在粉色盒子的上方,我們可以為z-index
設置一個更高的值。
如果我為黃色盒子設置了z-index: 4
,該值要比z-index: 3
高,但是並沒有看到任何變化。人們通常視圖通過設置一個巨大的數字來強制改變層疊順序,比如說設置z-index: 9999
,但這樣做沒有任何效果。如果在項目中看到這樣的z-index
值,那就屬於壞程式碼。我們要盡量避免這種行為。
導致上述設置不生效的根本原因,是由於z-index
在層疊上下文中的行為。
為了演示這一點,讓我們來看一個稍微複雜一點的例子,這是我從MDN網站上借鑒來的。
<header class="site-header blue">
<h1>Header</h1>
<code>position: relative;<br/>
z-index: 5;</code>
</header>
<main class="site-content pink">
<div class="box1 yellow">
<h1>Content box 1</h1>
<code>position: relative;<br/>
z-index: 6;</code>
</div>
<h1>Main content</h1>
<code>position: absolute;<br/>
z-index: 4;</code>
<div class="box2 yellow">
<h1>Content box 2</h1>
<code>position: relative;<br/>
z-index: 1;</code>
</div>
<div class="box3 yellow">
<h1>Content box 3</h1>
<code>position: absolute;<br/>
z-index: 3;</code>
</div>
</main>
<footer class="site-footer green">
<h1>Footer</h1>
<code>position: relative;<br/>
z-index: 2;</code>
</footer>
.blue {background: hsla(190,81%,67%,0.8); color: #1c1c1c;}
.purple {background: hsla(261,100%,75%,0.8);}
.green {background: hsla(84,76%,53%,0.8); color: #1c1c1c;}
.yellow {background: hsla(61,59%,66%,0.8); color: #1c1c1c;}
.pink {background: hsla(329,58%,52%,0.8);}
header, footer, main, div {
position: relative;
border: 1px dashed #000;
}
h1 {
font: inherit;
font-weight: bold;
}
.site-header, .site-footer {
padding: 10px;
}
.site-header {
z-index: 5;
top: -30px;
margin-bottom: 210px;
}
.site-footer {
z-index: 2;
}
.site-content {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
padding: 40px 20px 20px;
}
.box1 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
.box2 {
z-index: 1;
width: 400px;
margin-top: 15px;
padding: 5px 10px;
}
.box3 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 250px;
padding-top: 125px;
text-align: center;
}
在這裡,我們有一個header
,footer
和main
容器,就跟以前一樣。但是在site-content
內部,我們有三個盒子,它們都被定位了,並賦予了z-index
。
讓我們首先看一下三個主要容器 – header
,footer
和main
。
header
的z-index
值為5,因此出現在z-index
值為4的main
之上,footer
的z-index
值為2,因此出現在main
之下。目前為止一切順利吧?很好。
main
容器內的三個盒子讓事情變得撲朔迷離起來。
Content box 1的z-index
值為6,但出現在header
下面,而header
的z-index
值為5。
Content box 2的z-index
值為1,但出現在footer
上面,而footer
的z-index
值為2。
這究竟發生了啥?
所有疑慮都可以通過以下事實來解釋:所有的z-index
值都是在其父級層疊上下文中生效的。因為父容器.site-content
相比footer
而言,有一個更高的z-index
值,因此.site-content
中的任何定位元素都將在該上下文中計算。
在層疊上下文中思考層疊順序的一個好方法是,把它看作是嵌套有序列表中的一個子項目。按照這種思路可以寫成如下格式:
-
Header:
z-index: 5
-
Main:
z-index: 4
- Box 1:
z-index: 4.6
- Box 2:
z-index: 4.1
- Box 3:
z-index: 4.3
- Box 1:
-
Footer:
z-index: 2
因此,即使header
是z-index: 5
,content box 1是z-index: 6
,但content box 1的渲染順序是4.6,仍然小於5。因此,content box 1在header
下面。
剛開始確實有點亂,但隨著練習,開始有眉目了。
z-index只作用於定位元素
如果你想控制元素的層疊順序,你可以使用z-index
達到目的。但是,只有當該元素的position
值為absolute
、relative
或fixed
時,z-index
才會產生影響。
用position
精確地放置元素,對於建立複雜的布局或有趣的UI模式來說是不錯的。但通常只是想要控制層疊的順序,而不把元素從它在頁面上的原始位置移開。
如果是這種情況,你可以只設置position: relative
,而不提供top
、right
、bottom
或left
的任何值。該元素將保持在其在頁面上的原始位置,文檔流不會被打斷,z-index
值將會生效。
z-index可以是負值
分層元素通常是為了建立複雜的圖形或UI組件。這通常意味著將分層元素彼此重疊,並設置不斷增加的z-index
值。要把一個元素放在另一個元素的下面,它只需要有一個較低的z-index
值,但這個較低的值可以是負值。
當使用偽元素並希望將其定位在其父元素的內容之後時,負值的z-index
是非常有用的。
由於層疊上下文的工作方式,對於任何:before
或:after
元素,如果它們要被定位在其父元素的文本內容後面,那麼它們需要一個負的z-index
值。
z-index策略
讓我們用我在項目中應用z-index
的一個簡單策略來總結一下。
以前,我們使用個位數遞增來設置z-index
值,但如果你想在兩個設置了z-index: 3
和z-index: 4
的元素之間添加一個新的元素,你該怎麼辦?你必須同時改變更多的值。這可能會成為問題,並容易在網站的其他部分破壞CSS。
使用100步長設置z-index
在處理z-index
時,經常會看到這樣的程式碼:
.modal {
z-index: 99999;
}
這樣的程式碼對我來說非常粗糙,當附加上!important
時,會更加糟糕。當看到這樣的值時,往往意味著開發者不了解層疊上下文,並試圖強制一個層在另一個層的上面。
與其使用像9999、53或12這樣的任意數字,不如使我們的z-index
比例系統化,為程式帶來更多秩序。這裡我將使用以100為基礎進行遞增的z-index
值。
.layer-one {z-index: 100;}
.layer-two {z-index: 200;}
.layer-three {z-index: 300;}
我這樣做是為了保持事情的條理性,同時也是為了注意整個項目中使用的眾多不同的層。另一個好處是,如果需要在其他兩個圖層之間添加一個新的圖層,有99個潛在的值可以挑選。
當建立一個z-index
系統時,這種手動方法是相當可靠的,但當與像Sass這樣的預處理器的能力相結合時,可以變得更加靈活。
原文鏈接://www.sitepoint.com/atoz-css-z-index/