摘要:栗子有兩個(gè),被包裹在一個(gè)里,被包裹在另一個(gè)盒子里,同時(shí)為兩個(gè)和設(shè)置和屬性效果我們發(fā)下,雖然元素的值為,遠(yuǎn)大于和的值,但是由于的父元素產(chǎn)生的層疊上下文的的值為,的父元素所產(chǎn)生的層疊上下文的值為,所以永遠(yuǎn)在和下面。
前言
最近,在項(xiàng)目中遇到一個(gè)關(guān)于CSS中元素z-index屬性的問(wèn)題,具體問(wèn)題不太好描述,總結(jié)起來(lái)就是當(dāng)給元素和父元素色設(shè)置position屬性和z-index相關(guān)屬性后,頁(yè)面上渲染的元素層級(jí)結(jié)果和我預(yù)想的不一樣。根據(jù)自己之前的理解,也沒(méi)找到一個(gè)合理的解釋。我知道,肯定是我對(duì)相關(guān)屬性的細(xì)節(jié)理解存在問(wèn)題,所以結(jié)合官方文檔和在網(wǎng)上各種搜集整理,明白了其中的原因。寫(xiě)下這篇文章,和大家分享有關(guān)CSS中層疊上下文、層疊等級(jí)、層疊順序以及z-index相關(guān)的一整套技術(shù)細(xì)節(jié)。
如果存在什么錯(cuò)誤或重要遺漏或者有什么疑問(wèn),歡迎留言指正、討論!感謝!
本文已同步至我的個(gè)人主頁(yè)。更多內(nèi)容,歡迎訪問(wèn)我的GitHub主頁(yè),謝謝關(guān)注和支持!
一個(gè)“片面”的理解以往,由于自己使用z-index的頻率不大,所以對(duì)這個(gè)CSS屬性存在比較片面的認(rèn)識(shí)。一直認(rèn)為z-index就是用來(lái)描述定義一個(gè)元素在屏幕Z軸上的堆疊順序。z-index值越大在Z軸上就越靠上,也就是離屏幕觀察者越近。最后才發(fā)現(xiàn)這個(gè)認(rèn)識(shí)存在很大的問(wèn)題:
首先,z-index屬性值并不是在任何元素上都有效果。它僅在定位元素(定義了position屬性,且屬性值為非static值的元素)上有效果。
判斷元素在Z軸上的堆疊順序,不僅僅是直接比較兩個(gè)元素的z-index值的大小,這個(gè)堆疊順序?qū)嶋H由元素的層疊上下文、層疊等級(jí)共同決定。
要想完全理解一個(gè)東西,首先要明白它是什么,也就是它的定義。我們先看看上面提到的層疊上下文、層疊等級(jí)、層疊順序都是什么?定義又太過(guò)抽象,后面會(huì)再用一個(gè)具象的比喻來(lái)讓你徹底明白它們到底是什么,有什么聯(lián)系。
什么是“層疊上下文”層疊上下文(stacking context),是HTML中一個(gè)三維的概念。在CSS2.1規(guī)范中,每個(gè)盒模型的位置是三維的,分別是平面畫(huà)布上的X軸,Y軸以及表示層疊的Z軸。一般情況下,元素在頁(yè)面上沿X軸Y軸平鋪,我們察覺(jué)不到它們?cè)?b>Z軸上的層疊關(guān)系。而一旦元素發(fā)生堆疊,這時(shí)就能發(fā)現(xiàn)某個(gè)元素可能覆蓋了另一個(gè)元素或者被另一個(gè)元素覆蓋。
如果一個(gè)元素含有層疊上下文,(也就是說(shuō)它是層疊上下文元素),我們可以理解為這個(gè)元素在Z軸上就“高人一等”,最終表現(xiàn)就是它離屏幕觀察者更近。
具象的比喻:你可以把層疊上下文元素理解為理解為該元素當(dāng)了官,而其他非層疊上下文元素則可以理解為普通群眾。凡是“當(dāng)了官的元素”就比普通元素等級(jí)要高,也就是說(shuō)元素在Z軸上更靠上,更靠近觀察者。什么是“層疊等級(jí)”
那么,層疊等級(jí)指的又是什么?層疊等級(jí)(stacking level,叫“層疊級(jí)別”/“層疊水平”也行)
在同一個(gè)層疊上下文中,它描述定義的是該層疊上下文中的層疊上下文元素在Z軸上的上下順序。
在其他普通元素中,它描述定義的是這些普通元素在Z軸上的上下順序。
說(shuō)到這,可能很多人疑問(wèn)了,不論在層疊上下文中還是在普通元素中,層疊等級(jí)都表示元素在Z軸上的上下順序,那就直接說(shuō)它描述定義了所有元素在Z軸上的上下順序就OK啊!為什么要分開(kāi)描述?
為了說(shuō)明原因,先舉個(gè)栗子:
具象的比喻:我們之前說(shuō)到,處于層疊上下文中的元素,就像是元素當(dāng)了官,等級(jí)自然比普通元素高。再想象一下,假設(shè)一個(gè)官員A是個(gè)省級(jí)領(lǐng)導(dǎo),他下屬有一個(gè)秘書(shū)a-1,家里有一個(gè)保姆a-2。另一個(gè)官員B是一個(gè)縣級(jí)領(lǐng)導(dǎo),他下屬有一個(gè)秘書(shū)b-1,家里有一個(gè)保姆b-2。a-1和b-1雖然都是秘書(shū),但是你想一個(gè)省級(jí)領(lǐng)導(dǎo)的秘書(shū)和一個(gè)縣級(jí)領(lǐng)導(dǎo)的秘書(shū)之間有可比性么?甚至保姆a-2都要比秘書(shū)b-1的等級(jí)高得多。誰(shuí)大誰(shuí)小,誰(shuí)高誰(shuí)低一目了然,所以根本沒(méi)有比較的意義。只有在A下屬的a-1、a-2以及B下屬的b-1、b-2中相互比較大小高低才有意義。
再類(lèi)比回“層疊上下文”和“層疊等級(jí)”,就得出一個(gè)結(jié)論:
普通元素的層疊等級(jí)優(yōu)先由其所在的層疊上下文決定。
層疊等級(jí)的比較只有在當(dāng)前層疊上下文元素中才有意義。不同層疊上下文中比較層疊等級(jí)是沒(méi)有意義的。
如何產(chǎn)生“層疊上下文”前面說(shuō)了那么多,知道了“層疊上下文”和“層疊等級(jí)”,其中還有一個(gè)最關(guān)鍵的問(wèn)題:到底如何產(chǎn)生層疊上下文呢?如何讓一個(gè)元素變成層疊上下文元素呢?
其實(shí),層疊上下文也基本上是有一些特定的CSS屬性創(chuàng)建的,一般有3種方法:
HTML中的根元素本身j就具有層疊上下文,稱(chēng)為“根層疊上下文”。
普通元素設(shè)置position屬性為非static值并設(shè)置z-index屬性為具體數(shù)值,產(chǎn)生層疊上下文。
CSS3中的新屬性也可以產(chǎn)生層疊上下文。
至此,終于可以上代碼了,我們用代碼說(shuō)話,來(lái)驗(yàn)證上面的結(jié)論:
栗子1:
有兩個(gè)div,p.a、p.b被包裹在一個(gè)div里,p.c被包裹在另一個(gè)盒子里,只為.a、.b、.c設(shè)置position和z-index屬性
a
b
c
效果:
因?yàn)閜.a、p.b、p.c三個(gè)的父元素div都沒(méi)有設(shè)置z-index,所以不會(huì)產(chǎn)生層疊上下文,所以.a、.b、.c都處于由標(biāo)簽產(chǎn)生的“根層疊上下文”中,屬于同一個(gè)層疊上下文,此時(shí)誰(shuí)的z-index值大,誰(shuí)在上面。
栗子2:
有兩個(gè)div,p.a、p.b被包裹在一個(gè)div里,p.c被包裹在另一個(gè)盒子里,同時(shí)為兩個(gè)div和.a、.b、.c設(shè)置position和z-index屬性
a
b
c
效果:
我們發(fā)下,雖然p.c元素的z-index值為9999,遠(yuǎn)大于p.a和p.b的z-index值,但是由于p.a、p.b的父元素div.box1產(chǎn)生的層疊上下文的z-index的值為2,p.c的父元素div.box2所產(chǎn)生的層疊上下文的z-index值為1,所以p.c永遠(yuǎn)在p.a和p.b下面。
同時(shí),如果我們只更改p.a和p.b的z-index值,由于這兩個(gè)元素都在父元素div.box1產(chǎn)生的層疊上下文中,所以,誰(shuí)的z-index值大,誰(shuí)在上面。
什么是“層疊順序”說(shuō)完“層疊上下文”和“層疊等級(jí)”,我們?cè)賮?lái)說(shuō)說(shuō)“層疊順序”。“層疊順序”(stacking order)表示元素發(fā)生層疊時(shí)按照特定的順序規(guī)則在Z軸上垂直顯示。由此可見(jiàn),前面所說(shuō)的“層疊上下文”和“層疊等級(jí)”是一種概念,而這里的“層疊順序”是一種規(guī)則。
在不考慮CSS3的情況下,當(dāng)元素發(fā)生層疊時(shí),層疊順訊遵循上面途中的規(guī)則。
這里值得注意的是:
左上角"層疊上下文background/border"指的是層疊上下文元素的背景和邊框。
inline/inline-block元素的層疊順序要高于block(塊級(jí))/float(浮動(dòng))元素。
單純考慮層疊順序,z-index: auto和z-index: 0在同一層級(jí),但這兩個(gè)屬性值本身是有根本區(qū)別的。
對(duì)于上面第2條,為什么inline/inline-block元素的層疊順序要高于block(塊級(jí))/float(浮動(dòng))元素?這個(gè)大家可以思考一下!你要的“套路”
其實(shí)很簡(jiǎn)單,像border/background屬于裝飾元素的屬性,浮動(dòng)和塊級(jí)元素一般用來(lái)頁(yè)面布局,而網(wǎng)頁(yè)設(shè)計(jì)之初最重要的就是文字內(nèi)容,所以在發(fā)生層疊時(shí)會(huì)優(yōu)先顯示文字內(nèi)容,保證其不被覆蓋。
上面說(shuō)了那么多,可能你還是有點(diǎn)懵。這么多概念規(guī)則,來(lái)點(diǎn)最實(shí)際的,有沒(méi)有一個(gè)“套路”當(dāng)遇到元素層疊時(shí),能很清晰地判斷出他們誰(shuí)在上誰(shuí)在下呢?答案是——肯定有啊!
1、首先先看要比較的兩個(gè)元素是否處于同一個(gè)層疊上下文中:光說(shuō)不練假把式
??????1.1如果是,誰(shuí)的層疊等級(jí)大,誰(shuí)在上面(怎么判斷層疊等級(jí)大小呢?——看“層疊順序”圖)。
??????1.2如果兩個(gè)元素不在統(tǒng)一層疊上下文中,請(qǐng)先比較他們所處的層疊上下文的層疊等級(jí)。
2、當(dāng)兩個(gè)元素層疊等級(jí)相同、層疊順序相同時(shí),在DOM結(jié)構(gòu)中后面的元素層疊等級(jí)在前面元素之上。
對(duì)于技術(shù)學(xué)習(xí),代碼展示是最直觀最易懂的方式之一。話不多說(shuō),直接上代碼,我們通過(guò)以下幾個(gè)“栗子”,來(lái)進(jìn)一步驗(yàn)證掌握上面的結(jié)論。
栗子1:
效果:
說(shuō)明:.box1/.box2雖然設(shè)置了position: relative,但是z-index: auto的情況下,這兩個(gè)div還是普通元素,并沒(méi)有產(chǎn)生層疊上下文。所以,child1/.child2屬于元素的“根層疊上下文”中,此時(shí),誰(shuí)的z-index值大,誰(shuí)在上面。
栗子2:
對(duì)于栗子1中的CSS代碼,我們只把.box1/.box2的z-index屬性值改為數(shù)值0,其余不變。
.box1, .box2 { position: relative; z-index: 1; } ...
效果:
說(shuō)明: 此時(shí),我們發(fā)現(xiàn),僅僅修改了.box1/.box2的z-index屬性值改為數(shù)值0,最終結(jié)果完全相反。這時(shí).child2覆蓋在了.child1上面。原因是什么呢?很簡(jiǎn)單:因?yàn)樵O(shè)置z-index: 0后,.box1/.box2產(chǎn)生了各自的層疊上下文,這時(shí)候要比較.child1/.child2的層疊關(guān)系完全由父元素.box1/.box2的層疊關(guān)系決定。但是.box1/.box2的z-index值都為0,都是塊級(jí)元素(所以它們的層疊等級(jí),層疊順序是相同的),這種情況下,在DOM結(jié)構(gòu)中后面的覆蓋前面的,所以.child2就在上面。
CSS3中的屬性對(duì)層疊上下文的影響CSS3中出現(xiàn)了很多新屬性,其中一些屬性對(duì)層疊上下文也產(chǎn)生了很大的影響。如下:
父元素的display屬性值為flex|inline-flex,子元素z-index屬性值不為auto的時(shí)候,子元素為層疊上下文元素;
元素的opacity屬性值不是1;
元素的transform屬性值不是none;
元素mix-blend-mode屬性值不是normal`;
元素的filter屬性值不是none;
元素的isolation屬性值是isolate;
will-change指定的屬性值為上面任意一個(gè);
元素的-webkit-overflow-scrolling屬性值設(shè)置為touch。
CSS3中,元素屬性滿足以上條件之一,就會(huì)產(chǎn)生層疊上下文。我們用第1條來(lái)做一個(gè)簡(jiǎn)單的解釋說(shuō)明。
栗子1:
parentchild
效果:
說(shuō)明: 我們發(fā)現(xiàn),.child被.parent覆蓋了。按照“套路”來(lái)分析一下:
雖然.parent設(shè)置了z-index屬性值,但是沒(méi)有設(shè)置position屬性,z-index無(wú)效,所以沒(méi)有產(chǎn)生層疊上下文,.parent還是普通的塊級(jí)元素。此時(shí),在層疊順序規(guī)則中,z-index值小于0的.child會(huì)被普通的block塊級(jí)元素.parent覆蓋。
對(duì)于上面的栗子,我們只修改.box的屬性,設(shè)置display: flex,其余屬性和DOM結(jié)構(gòu)不變。
.box { display: flex; }
效果:
說(shuō)明: 當(dāng)給.box設(shè)置display: flex時(shí),.parent就變成層疊上下文元素,根據(jù)層疊順序規(guī)則,層疊上下文元素的background/border的層疊等級(jí)小于z-index值小于0的元素的層疊等級(jí),所以z-index值為-1的.child在.parent上面。
小測(cè)試下面的代碼,我會(huì)把最終頁(yè)面渲染的結(jié)果放在代碼之后,有興趣的“童鞋”可以分析一下,各個(gè)元素的層疊等級(jí),最后來(lái)確定這些元素哪個(gè)在上哪個(gè)在下。
parentchild1child2child2-1child2-2
效果:
以上的內(nèi)容有一部分內(nèi)容參考了以下兩位大神的博客,寫(xiě)的很好,也很清晰,推薦大家看一看,你會(huì)對(duì)相關(guān)知識(shí)點(diǎn)掌握的更清晰。
張?chǎng)涡?《深入理解CSS中的層疊上下文和層疊順序》
AMInInsist-《CSS 中的z-index屬性》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/113844.html
摘要:栗子有兩個(gè),被包裹在一個(gè)里,被包裹在另一個(gè)盒子里,同時(shí)為兩個(gè)和設(shè)置和屬性效果我們發(fā)下,雖然元素的值為,遠(yuǎn)大于和的值,但是由于的父元素產(chǎn)生的層疊上下文的的值為,的父元素所產(chǎn)生的層疊上下文的值為,所以永遠(yuǎn)在和下面。 前言 最近,在項(xiàng)目中遇到一個(gè)關(guān)于CSS中元素z-index屬性的問(wèn)題,具體問(wèn)題不太好描述,總結(jié)起來(lái)就是當(dāng)給元素和父元素色設(shè)置position屬性和z-index相關(guān)屬性后,頁(yè)面...
摘要:當(dāng)?shù)诙拥娜萜骱凶由?jí)為層疊上下文時(shí),紅色盒子及灰色盒子的軸層級(jí)受制于第二層的容器盒子。當(dāng)元素處于同一層疊上下文內(nèi)時(shí)可按照如下規(guī)則進(jìn)行層疊判斷。 本文首發(fā)于政采云前端團(tuán)隊(duì)博客:CSS 層疊上下文(Stacking Context) 在網(wǎng)頁(yè)制作的過(guò)程中,元素與元素之間的位置關(guān)系,在坐標(biāo)軸上一般可體現(xiàn)為 X 軸、Y 軸和 Z 軸。對(duì)于 X 軸和 Y 軸的定位大多數(shù)開(kāi)發(fā)都能比較直觀的搞清楚...
摘要:標(biāo)簽中的一切都被置于這個(gè)默認(rèn)的層疊上下文的一個(gè)層疊層上物品放在桌子上。在層疊上下文中,其子元素按照上面解釋的規(guī)則進(jìn)行層疊。在中所有的盒模型元素都處于三維坐標(biāo)系中。 最近在項(xiàng)目的過(guò)程中遇到了一個(gè)問(wèn)題,menu-bar希望始終顯示在最上面,而在之后的元素都顯示在它之下,當(dāng)時(shí)設(shè)置了 z-index 也沒(méi)有效果,不知道什么原因,因此找了一下css有關(guān)層疊方面的資料,解決了這個(gè)問(wèn)題,這里記錄一下...
摘要:如果同級(jí)父元素不是層疊上下文元素就不需要看父元素的眼色了文章到這里就結(jié)束了,希望看完這篇文章的同學(xué)可以徹底理解。 今天寫(xiě)代碼用antd-mobile的checkbox時(shí)候,想在內(nèi)容文本后面添加一個(gè)icon,并且需要對(duì)這個(gè)icon綁定事件,發(fā)現(xiàn)綁定之后怎么也點(diǎn)不中,調(diào)試發(fā)現(xiàn)原來(lái)被層層嵌套的dom元素蓋住了,肯定是z-index在作祟。可是按照我之前對(duì)z-index的了解(自信滿滿)卻怎么...
閱讀 1057·2021-11-12 10:34
閱讀 984·2021-09-30 09:56
閱讀 667·2019-08-30 15:54
閱讀 2601·2019-08-30 11:14
閱讀 1464·2019-08-29 16:44
閱讀 3203·2019-08-29 16:35
閱讀 2489·2019-08-29 16:22
閱讀 2440·2019-08-29 15:39