CSS 中重要的層疊概念詳解

最近在項(xiàng)目的過(guò)程中遇到了一個(gè)問(wèn)題,menu-bar希望始終顯示在最上面,而在之后的元素都顯示在它之下,當(dāng)時(shí)設(shè)置了 z-index 也沒(méi)有效果,不知道什么原因,因此找了一下css有關(guān)層疊方面的資料,解決了這個(gè)問(wèn)題,這里記錄一下~
屏幕是一個(gè)二維平面,然而HTML元素卻是排列在三維坐標(biāo)系中,x為水平位置,y為垂直位置,z為屏幕由內(nèi)向外方向的位置,我們?cè)诳雌聊坏臅r(shí)候是沿著z軸方向從外向內(nèi)的;由此,元素在用戶視角就形成了層疊的關(guān)系,某個(gè)元素可能覆蓋了其他元素也可能被其他元素覆蓋;
那么這里有幾個(gè)重要的概念: 層疊上下文 (堆疊上下文, Stacking Context)、 層疊等級(jí) (層疊水平, Stacking Level)、 層疊順序 (層疊次序, 堆疊順序, Stacking Order)、 z-index
聲明:
- 以下定位元素指的是
position:absolute|fixed|relative|sticky
- 以下非定位元素指的是
position:initial|static
- 關(guān)于層疊上下文還有一個(gè)類似的概念: 塊級(jí)格式化上下文 (BFC, Block Formatting Context),可以參考一下 CSS 中重要的BFC,其中還介紹了一些文檔流的內(nèi)容;
- 本文蠻長(zhǎng)的,但是如果你有勇氣看完,那應(yīng)該對(duì)層疊有關(guān)概念就基本掌握了 (~o ̄▽ ̄)~
1. 層疊上下文 (Stacking Context)
層疊上下文(堆疊上下文, Stacking Context),是HTML中一個(gè)三維的概念。在CSS2.1規(guī)范中,每個(gè)元素的位置是三維的,當(dāng)元素發(fā)生層疊,這時(shí)它可能覆蓋了其他元素或者被其他元素覆蓋;排在z軸越靠上的位置,距離屏幕觀察者越近
文章<關(guān)于z-index 那些你不知道的事>有一個(gè)很好的比喻,這里引用一下;
可以想象一張桌子,上面有一堆物品,這張桌子就代表著一個(gè)層疊上下文。如果在第一張桌子旁還有第二張桌子,那第二張桌子就代表著另一個(gè)層疊上下文。
現(xiàn)在想象在第一張桌子上有四個(gè)小方塊,他們都直接放在桌子上。在這四個(gè)小方塊之上有一片玻璃,而在玻璃片上有一盤水果。這些方塊、玻璃片、水果盤,各自都代表著層疊上下文中一個(gè)不同的層疊層,而這個(gè)層疊上下文就是桌子。
每一個(gè)網(wǎng)頁(yè)都有一個(gè)默認(rèn)的層疊上下文。這個(gè)層疊上下文(桌子)的根源就是 <html></html>
。html標(biāo)簽中的一切都被置于這個(gè)默認(rèn)的層疊上下文的一個(gè)層疊層上(物品放在桌子上)。
當(dāng)你給一個(gè)定位元素賦予了除 auto
外的 z-index 值時(shí),你就創(chuàng)建了一個(gè)新的層疊上下文,其中有著獨(dú)立于頁(yè)面上其他層疊上下文和層疊層的層疊層, 這就相當(dāng)于你把另一張桌子帶到了房間里。
層疊上下文1 (Stacking Context 1)是由文檔根元素形成的, 層疊上下文2和3 (Stacking Context 2, 3) 都是層疊上下文1 (Stacking Context 1) 上的層疊層。他們各自也都形成了新的層疊上下文,其中包含著新的層疊層。
在層疊上下文中,其子元素按照上面解釋的規(guī)則進(jìn)行層疊。形成層疊上下文的方法有:
- 根元素
<html></html>
position
值為absolute|relative
,且z-index
值不為auto
position
值為fixed|sticky
z-index
值不為auto
的flex元素,即:父元素display:flex|inline-flex
opacity
屬性值小于1
的元素transform
屬性值不為none
的元素mix-blend-mode
屬性值不為normal
的元素filter
、perspective
、clip-path
、mask
、mask-image
、mask-border
、motion-path
值不為none
的元素perspective
值不為none
的元素isolation
屬性被設(shè)置為isolate
的元素will-change
中指定了任意 CSS 屬性,即便你沒(méi)有直接指定這些屬性的值-webkit-overflow-scrolling
屬性被設(shè)置touch
的元素
總結(jié):
層疊上下文可以包含在其他層疊上下文中,并且一起組建了一個(gè)有層級(jí)的層疊上下文
每個(gè)層疊上下文完全獨(dú)立于它的兄弟元素,當(dāng)處理層疊時(shí)只考慮子元素,這里類似于BFC
每個(gè)層疊上下文是自包含的:當(dāng)元素的內(nèi)容發(fā)生層疊后,整個(gè)該元素將會(huì) 在父級(jí)疊上下文 中按順序進(jìn)行層疊
2. 層疊等級(jí) (Stacking Level)
層疊等級(jí)(層疊水平, Stacking Level) 決定了同一個(gè)層疊上下文中元素在z軸上的顯示順序的 概念 ;
- 普通元素的層疊等級(jí)優(yōu)先由其所在的層疊上下文決定
- 層疊等級(jí)的比較只有在同一個(gè)層疊上下文元素中才有意義
- 在同一個(gè)層疊上下文中,層疊等級(jí)描述定義的是該層疊上下文中的元素在Z軸上的上下順序
注意,層疊等級(jí)并不一定由 z-index 決定,只有定位元素的層疊等級(jí)才由 z-index 決定,其他類型元素的層疊等級(jí)由層疊順序、他們?cè)贖TML中出現(xiàn)的順序、他們的父級(jí)以上元素的層疊等級(jí)一同決定,詳細(xì)的規(guī)則見(jiàn)下面層疊順序的介紹。
3. z-index
在 CSS 2.1 中, 所有的盒模型元素都處于三維坐標(biāo)系中。除了我們常用的橫坐標(biāo)和縱坐標(biāo), 盒模型元素還可以沿著"z 軸"層疊擺放, 當(dāng)他們相互覆蓋時(shí), z 軸順序就變得十分重要。
-- CSS 2.1 Section 9.9.1 - Layered presentation
z-index 只適用于定位的元素,對(duì)非定位元素?zé)o效,它可以被設(shè)置為正整數(shù)、負(fù)整數(shù)、0、auto,如果一個(gè)定位元素沒(méi)有設(shè)置 z-index,那么默認(rèn)為auto;
元素的 z-index 值只在同一個(gè)層疊上下文中有意義。如果父級(jí)層疊上下文的層疊等級(jí)低于另一個(gè)層疊上下文的,那么它 z-index 設(shè)的再高也沒(méi)用。所以如果你遇到 z-index 值設(shè)了很大,但是不起作用的話,就去看看它的父級(jí)層疊上下文是否被其他層疊上下文蓋住了。
4. 層疊順序 (Stacking Order)
層疊順序(層疊次序, 堆疊順序, Stacking Order) 描述的是元素在同一個(gè)層疊上下文中的順序 規(guī)則 ,從層疊的底部開(kāi)始,共有七種層疊順序:
- 背景和邊框:形成層疊上下文的元素的背景和邊框。
- 負(fù)z-index值:層疊上下文內(nèi)有著負(fù)z-index值的定位子元素,負(fù)的越大層疊等級(jí)越低;
- 塊級(jí)盒:文檔流中塊級(jí)、非定位子元素;
- 浮動(dòng)盒:非定位浮動(dòng)元素;
- 行內(nèi)盒:文檔流中行內(nèi)、非定位子元素;
- z-index: 0:z-index為0或auto的定位元素, 這些元素形成了新的層疊上下文;
- 正z-index值:z-index 為正的定位元素,正的越大層疊等級(jí)越高;
同一個(gè)層疊順序的元素按照在HTML里出現(xiàn)的順序?qū)盈B;第7級(jí)順序的元素會(huì)顯示在之前順序元素的上方,也就是看起來(lái)覆蓋了更低級(jí)的元素:
5. 實(shí)戰(zhàn)
5.1 普通情況
三個(gè) relative
定位的 div
塊中各有 absolute
的不同顏色的 span.red
、 span.green
、 span.blue
,它們都設(shè)置了 position:absolute
;
參見(jiàn)Codepen - 普通情況
那么當(dāng)沒(méi)有元素包含z-index屬性時(shí),這個(gè)例子中的元素按照如下順序?qū)盈B(從底到頂順序):
- 根元素的背景和邊界
- 塊級(jí)非定位元素按HTML中的出現(xiàn)順序?qū)盈B
- 行內(nèi)非定位元素按HTML中的出現(xiàn)順序?qū)盈B
- 定位元素按HTML中的出現(xiàn)順序?qū)盈B
紅綠藍(lán)都屬于 z-index 為auto的定位元素,因此按照7層層疊順序規(guī)則來(lái)說(shuō)同屬于層疊順序第6級(jí),所以按HTML中的出現(xiàn)順序?qū)盈B: 紅->綠->藍(lán)
5.2 在相同層疊上下文的父元素內(nèi)的情況
紅綠位于一個(gè) div.first-box
下,藍(lán)位于 div.second-box
下,紅綠藍(lán)都設(shè)置了 position:absolute
, first-box
與 second-box
都設(shè)置了 position:relative
;
參見(jiàn)Codepen - 父元素不同但都位于根元素下
這個(gè)例子中,紅藍(lán)綠元素的父元素 first-box
與 second-box
都沒(méi)有生成新的層疊上下文,都屬于根層疊上下文中的元素,且都是層疊順序第6級(jí),所以按HTML中的出現(xiàn)順序?qū)盈B: 紅->綠->藍(lán)
5.3 給子元素增加 z-index
紅綠位于一個(gè) div.first-box
下,藍(lán)黃位于 div.second-box
下,紅綠藍(lán)都設(shè)置了 position:absolute
,如果這時(shí)給綠加一個(gè)屬性 z-index:1
,那么此時(shí) .green
位于最上面;
如果再在 .second-box
下 .green
后加一個(gè)絕對(duì)定位的 span.gold
,設(shè)置 z-index:-1
,那么它將位于紅綠藍(lán)的下面;
參見(jiàn)Codepen - 設(shè)置了z-index
這個(gè)例子中,紅藍(lán)綠黃元素的父元素中都沒(méi)有生成新的層疊上下文,都屬于根層疊上下文中的元素
紅藍(lán)都沒(méi)有設(shè)置 z-index,同屬于層疊順序中的第6級(jí),按HTML中的出現(xiàn)順序?qū)盈B;
- 綠設(shè)置了正的 z-index,屬于第7級(jí);
- 黃設(shè)置了負(fù)的 z-index,屬于第2級(jí);
所以這個(gè)例子中的從底到高顯示的順序就是: 黃->紅->藍(lán)->綠
5.4 在不同層疊上下文的父元素內(nèi)的情況
紅綠位于一個(gè) div.first-box
下,藍(lán)位于 div.second-box
下,紅綠藍(lán)都設(shè)置了 position:absolute
,如果 first-box
的z-index設(shè)置的比 second-box
的大,那么此時(shí)無(wú)論藍(lán)的 z-index 設(shè)置的多大 z-index:999
,藍(lán)都位于紅綠的下面;如果我們只更改紅綠的z-index值,由于這兩個(gè)元素都在父元素 first-box
產(chǎn)生的層疊上下文中,此時(shí)誰(shuí)的z-index值大,誰(shuí)在上面;
參見(jiàn)Codepen - 不同層疊上下文的父元素
這個(gè)例子中,紅綠藍(lán)都屬于設(shè)置了z-index的定位元素,不過(guò)他們的父元素創(chuàng)建了新的層疊上下文;
- 紅綠的父元素
first-box
是設(shè)置了正z-index的定位元素,因此創(chuàng)建了一個(gè)層疊上下文,屬于層疊順序中的第7級(jí); - 藍(lán)的父元素
second-box
也同樣創(chuàng)建了一個(gè)層疊上下文,屬于層疊順序中的第6級(jí); - 按照層疊順序,
first-box
中所有元素都排在second-box
上; - 紅綠都屬于層疊上下文
first-box
中且設(shè)置了不同的正 z-index,都屬于層疊順序中第7級(jí); - 藍(lán)屬于層疊上下文
second-box
,且設(shè)置了一個(gè)很大的正 z-index,屬于層疊元素中第7級(jí); - 雖然藍(lán)的 z-index 很大,但是因?yàn)?nbsp;
second-box
的層疊等級(jí)比first-box
小,因此位于紅綠之下;
所以這個(gè)例子中從低到到顯示的順序: 藍(lán)->紅->綠
(我遇到的的情況就屬于這個(gè)例子類似情形)
5.5 給子元素設(shè)置 opacity
紅綠位于 div.first-box
下,藍(lán)位于 div.second-box
下,紅綠藍(lán)都設(shè)置了 position:absolute
,綠設(shè)置了 z-index:1
,那么此時(shí)綠位于紅藍(lán)的最上面;
如果此時(shí)給 first-box
設(shè)置 opacity:.99
,這時(shí)無(wú)論紅綠的 z-index 設(shè)置的多大 z-index:999
,藍(lán)都位于紅綠的上面;
如果再在 .second-box
下 .green
后加一個(gè) span.gold
,設(shè)置 z-index:-1
,那么它將位于紅綠藍(lán)的下面;
參見(jiàn)Codepen - opacity的影響
之前已經(jīng)介紹了,設(shè)置 opacity
也可以形成層疊上下文,因此:
first-box
設(shè)置了opacity
,first-box
成為了一個(gè)新的層疊上下文;second-box
沒(méi)有形成新的層疊上下文,因此其中的元素都屬于根層疊上下文;- 黃屬于層疊順序中第2級(jí),紅綠屬于第7級(jí),
first-box
屬于第6級(jí),藍(lán)屬于層疊順序中第6級(jí)且按HTML出現(xiàn)順序位于first-box
之上;
所以這個(gè)例子中從低到到顯示的順序: 黃->紅->綠->藍(lán)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
css3+svg實(shí)現(xiàn)創(chuàng)意圖片層疊音樂(lè)播放樣式代碼
css3圖片層疊音樂(lè)播放樣式代碼是一款點(diǎn)擊圖片切換下一首音樂(lè)播放ui布局特效。2020-07-15- 這篇文章主要介紹了CSS中層疊上下文的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)2020-04-27
- 這篇文章主要介紹了css 層疊與z-index的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)2020-03-23
- 這篇文章主要介紹了css樣式層疊規(guī)則,本文通過(guò)實(shí)例代碼文字說(shuō)明給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-28
- 這篇文章主要介紹了CSS中的特指度和層疊問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-12