CSS 中的層疊概念
在css的世界中代态,每個元素都有一套自己的樣式規(guī)則寺惫,同時在網(wǎng)頁中,也遵循著一套默認(rèn)的排版規(guī)則蹦疑,從上到下西雀,從左到右進(jìn)行排列,可是對于復(fù)雜的業(yè)務(wù)需求歉摧,默認(rèn)的排版規(guī)則已經(jīng)不能滿足開發(fā)需求艇肴,所以我們需要去自定義元素的排列順序,達(dá)到我們的要求叁温,常用的屬性包括position, float, display, z-index等等,同時膝但,CSS3的到來,給網(wǎng)頁布局帶來了更多的可能性莺奸。這其中涉及到了幾個重要的概念丑孩,層疊上下文嚎杨、層疊水平以及層疊順序枫浙。
1古拴、什么是層疊上下文憨募?
層疊上下文(stacking context)是HTML元素的三維概念见秽,這些HTML元素在一條假想的相對于面向(電腦屏幕的)視窗或者網(wǎng)頁的用戶的z軸上延伸桅打,HTML元素依據(jù)其自身屬性按照優(yōu)先級順序占用層疊上下文的空間《焯拢可以理解為,具有層疊上下文的元素丽柿,在z軸上面比普通元素更高級魂挂,離用戶更近。
文檔中的層疊上下文由滿足以下任意一個條件的元素形成:
- 根元素 (HTML),
- z-index 值不為 "auto"的 絕對/相對定位坠非,
- 一個 z-index 值不為 "auto"的flex 項目 (flex item)果正,即:父元素 display: flex|inline-flex,
- opacity 屬性值小于 1 的元素(參考 the specification for opacity)辅肾,
- transform 屬性值不為 "none"的元素轮锥,
- mix-blend-mode 屬性值不為 "normal"的元素舍杜,
- filter值不為“none”的元素,
- perspective值不為“none”的元素既绩,
- isolation 屬性被設(shè)置為 "isolate"的元素,
- position: fixed
- 在 will-change 中指定了任意 CSS屬性私杜,即便你沒有直接指定這些屬性的值(參考 這篇文章)
- -webkit-overflow-scrolling 屬性被設(shè)置 “touch”的元素
簡而言之衰粹,層疊上下文分下面幾類:
- 頁面根元素天生具有層疊上下文,稱之為“根層疊上下文”铝耻,也就是HTML根元素蹬刷。
- z-index值為數(shù)值的定位元素的傳統(tǒng)層疊上下文。
- 其他CSS3屬性泡态。
2兽赁、什么是層疊水平?
層疊水平(stacking level)決定了同一個層疊上下文中元素在z軸上的顯示順序刀崖,決定了層疊上下文的層疊順序拍摇,也就是說層疊水平的討論僅僅限于層疊上下文中充活,對于普通元素并無意義。層疊水平高級的要覆蓋低級的混卵,那如何確定層疊水平的高低呢?由層疊順序決定蚁滋。
3辕录、什么是層疊順序?
層疊順序(stacking order)表示元素發(fā)生層疊時候有著特定的垂直顯示順序副女,注意蚣旱,這里跟上面兩個不一樣,上面的層疊上下文和層疊水平是概念沟涨,而這里的層疊順序是規(guī)則位隶。層疊順序基本可從下圖所示中獲知:
其中要注意以下幾點(diǎn):
- 位于最低水平的是層疊上下文的背景和邊框。每一個層疊順序適用于一個完整的層疊上下文篮昧,如果子元素也是一個層疊上下文笋妥,那么子元素也有一套完整自己的層疊順序規(guī)則春宣。
- 子元素的層疊上下文無法超過父元素的層疊上下文。
- 注意z-index: auto和z-index: 0的區(qū)別月帝,盡管二者都表示z-index: 0的層疊水平,但是僅限于層疊水平嚷辅,在層疊上下文的領(lǐng)域有很大差異
同時簸搞,層疊順序遵循一下排列規(guī)則:
- 同一個層疊上下文領(lǐng)域,層疊水平大的覆蓋層疊水平小的元素趁俊。
- 當(dāng)層疊水平一致的情況下寺擂,在DOM流下面的元素覆蓋上面的元素泼掠。
4般卑、傳統(tǒng)層疊上下文的創(chuàng)建
傳統(tǒng)層疊上下文通過position屬性爽雄,并配合z-index屬性創(chuàng)建。其中z-index屬性不能為默認(rèn)的auto值叹谁,如果值為auto乘盖,則該元素為普通元素,其和其子元素均屬于父級的層疊上下文(上圖中所示第3層)析苫,現(xiàn)在我們先看這樣的代碼:
這是一個很普通的html布局衩侥,效果圖如下:
可以看到紅色背景的div中包含了石原里美的照片矛物,現(xiàn)在讓我們稍微添加一下布局屬性
很容易想到履羞,石原里美的照片被紅色背景蓋住了
那如何在不改變照片樣式的情況下忆首,讓石原里美重回大家的視線呢糙及?我們可以嘗試修改父元素的樣式:
但是我們發(fā)現(xiàn),這并沒有生效妒潭,那么我們把z-index改成1試試
發(fā)現(xiàn)z-index值小的石原里美居然又回來啦■ㄔ郑現(xiàn)在我們讓情況變得復(fù)雜一些冯凹,我們把父元素的樣式清除,添加另一張圖片匈庭,這時我們發(fā)現(xiàn),圖片被牢牢的壓在下面阱持,那么我們試著改變一下父元素的樣式,將兩個div的z-index都改成相同的樣式值(如第二張圖)鸽扁。
我們發(fā)現(xiàn)z-index值更小的新垣結(jié)衣桶现,壓在了石原里美的身上骡和,不是應(yīng)該z-index值更大的在上面嗎相寇?
現(xiàn)在說明一下东囚,以上兩種情況的發(fā)生原因页藻,首先是第一種情況植兰,當(dāng)我們賦予石原里美position:absolute;z-index=-1時,由于她的父元素是一個普通元素废境,并沒有創(chuàng)建一個層疊上下文噩凹,因此毡咏,石原里美屬于上一級的層疊上下文呕缭,也就是根元素html修己,那么她的父元素和她自己屬于同一個層疊上下文領(lǐng)域(html)迎罗,按照層疊順序纹安,z-index為負(fù)的在普通元素下面,因此紅色背景覆蓋在了石原里美的身上啥刻。同樣的咪笑,改變父元素的z-index值為auto時窗怒,并沒有使父元素含有層疊上下文蓄拣。而當(dāng)父元素的z-index變成具體的值1時球恤,這個時候辜昵,就創(chuàng)建了一個層疊上下文,那么就相當(dāng)于把石原里美從html的手中”解救“了出來咽斧,她屬于父元創(chuàng)建的全新的層疊上下文中堪置,按照層疊順序,她會覆蓋在父元素的background之上张惹,重回我們面前舀锨。對于第二種情況,兩張照片的父元素只有positioned屬性時宛逗,均為普通元素坎匿,那么兩張照片同屬于根元素層疊上下文,遵循誰大誰上的原則雷激,石原里美壓在了新垣結(jié)衣的上面替蔬,當(dāng)我們給父元素一個不為auto的z-index的時候,都形成了一個層疊上下文屎暇,由于兩個z-index值相等承桥,那么遵循后來居上的原則, 新垣結(jié)衣所在的div覆蓋在最上面恭垦,同時,層疊上下文具有自成體系的特性,兩位姑娘的比較變成了優(yōu)先比較父元素的層疊順序贴铜,因此,兩位姑娘上面的z-index此時就不生效了轩褐。
需要額外注意的是,當(dāng)元素具有position:fixed屬性時拗踢,不管有沒有z-index屬性,自動創(chuàng)建層疊上下文君纫。
5、CSS3其他類型層疊上下文的創(chuàng)建
其他類型的層疊上下文包括:
- 一個 z-index 值不為 "auto"的flex 項目 (flex item),即:父元素 display: flex|inline-flex好乐,
- opacity 屬性值小于 1 的元素(參考 the specification for opacity),
- transform 屬性值不為 "none"的元素反璃,
- mix-blend-mode 屬性值不為 "normal"的元素,
- filter值不為“none”的元素淳蔼,
- perspective值不為“none”的元素穿稳,
- isolation 屬性被設(shè)置為 "isolate"的元素艰垂,
- position: fixed
- 在 will-change 中指定了任意 CSS屬性搔课,即便你沒有直接指定這些屬性的值(參考 這篇文章)
- -webkit-overflow-scrolling 屬性被設(shè)置 “touch”的元素
- 父元素為display:flex或者inline-flex的情況
現(xiàn)在我們先給新垣結(jié)衣放個假,我們對代碼做出以下調(diào)整:
注意我們給圖片一個負(fù)的z-index,當(dāng)我們知道境输,單獨(dú)給元素一個z-index是不起作用的,可實(shí)際上,石原里美被紅色背景牢牢遮住了强缘,這是為什么呢,因為要滿足兩個條件才能形成層疊上下文:條件1是父級需要是display:flex或者display:inline-flex水平栅哀,條件2是子元素的z-index不是auto痴柔,必須是數(shù)值。此時,這個子元素為層疊上下文元素糯耍,沒錯扭粱,注意了,是子元素,不是flex父級元素。
也就是說以清,圖片創(chuàng)建了一個層疊上下文,按照層疊順序凛虽,z-index為負(fù)值的被蓋在了普通元素紅色div的下面。
- Opacity 與層疊上下文
直接上代碼:
效果圖:
我們發(fā)現(xiàn)z-index=-1的圖片并沒有被覆蓋戳杀,因為當(dāng)我們賦予div opacity:0.5時题造,便創(chuàng)建了一個層疊上下文牵触,圖片屬于父元素的層疊上下文領(lǐng)域羹令,按照層疊順序福侈,圖片會覆蓋在背景之上
- transform屬性
代碼:
效果圖:
同樣的,transform屬性也會創(chuàng)建一個層疊上下文矮固。
-
filter屬性
image.png
image.png
filter屬性也會創(chuàng)建一個層疊上下文档址。
其余屬性尼摹,也會創(chuàng)建層疊上下文和二,大家如果感興趣可以嘗試一下
6、層疊上下文的層疊順序
討論了一些層疊上下文內(nèi)部元素的層疊順序和一些層疊上下文的創(chuàng)建方法,那么半醉,一個層疊上下文本身處于層疊順序中的那個層級呢梁钾?
用代碼驗證:
我們在兩張圖片中間插入一個寬度600px的綠色inline-block元素,驗證他們之間的層疊順序逊抡,效果圖如下:
可以看到姆泻,本來位于第5層的inline-block元素被兩個層疊上下文壓在了下面。其實(shí)層疊上下文的層疊順序被自動提升了冒嫡,規(guī)則是:
- 一旦成為定位元素拇勃,則自動賦予z-index屬性,默認(rèn)值為auto孝凌,層疊等級與z-index:0相同方咆。
- 而不是定位元素,則不支持z-index屬性的其他層疊上下文蟀架,存在天然的z-index:auto級別瓣赂,也就是說層疊等級與z-index:0的元素相同。
如果定位元素有z-index不為auto的值片拍,那么根據(jù)誰大誰上的原則煌集,按照z-index值進(jìn)行排列。
上圖中捌省,由于新垣結(jié)衣的dom順序在下面牙勘,因此覆蓋住了石原里美,但是二者在層疊順序表中所禀,又比綠色背景的inline-block等級高,綠色元素被覆蓋在最下面放钦。當(dāng)我們調(diào)換二者的順序色徘,就可證明:
以上就是關(guān)于層疊上下文和層疊等級的一些概念和使用。這樣在今后頁面布局的應(yīng)用中操禀,可以避免我們盲目使用z-index和定位褂策,來達(dá)到我們想要的頁面效果。