你可能对position和z-index有一些误解
一文詳解css中的position和z-index
- 🧃序言
- 🍷一、文章結構搶先知
- 🍸二、position
- 1. position的取值
- 2. 標準文檔流
- 3. 各取值解析
- (1)static
- (2)relative
- (3)absolute
- (4)fixed
- (5)sticky
- 🍹三、z-index
- 1. 一個片面的理解
- 2. z-index的取值
- 3. 層疊上下文
- (1)舉個例子
- (2)定義
- 4. 層疊等級
- (1)定義
- (2)舉個例子
- 5. 形成的條件
- 6. 層疊順序
- 7. 例子展示
- 🥂四、結束語
- 🐣彩蛋 One More Thing
- (:參考資料
- (:番外篇
🧃序言
最近在整理一些很偏的面經題,想起來很久以前被問到的一道題,就是 position 和 z-index 。短短 10min 問了這兩個屬性,大概直接把周一問懵了。那個時候的心情可能是這樣的……
于是,一鼓作氣,不懂的知識咱還是得補呀,萬一下回又直接被問懵了,那就是死不知悔改了不是。
最后,通過各種資料的查詢和理解,整理了下文。內容主要涵蓋 position 各個取值的解析以及關于 z-index 的使用。
下面開始進入本文的講解~🧐
🍷一、文章結構搶先知
在文章開始講解之前,我們先用一張思維導圖來了解本文所要講解的知識。詳情見下圖👇
了解完思維導圖之后,現在開始進入本文的講解。
🍸二、position
1. position的取值
通常情況下, position 有以下幾個取值。具體如下:
| static | 靜態定位 | 對象遵循標準文檔流,top,right,bottom,left 等屬性失效。 |
| relative | 相對定位 | 對象遵循標準文檔流中,依賴top,right,bottom,left 等屬性相對于該對象在標準文檔流中的位置進行偏移,同時可通過 z-index 定義層疊關系。 |
| absolute | 絕對定位 | 對象脫離標準文檔流,使用 top,right,bottom,left 等屬性進行絕對定位(相對于 static 定位以外的第一個父元素進行絕對定位) ,以及可通過 z-index 定義層疊關系。 |
| fixed | 固定定位 | 對象脫離標準文檔流,使用 top,right,bottom,left 等屬性進行絕對定位(相對于瀏覽器窗口進行絕對定位)同時可通過 z-index 定義層疊關系。 |
| sticky | 粘性定位 | 可以說是相對定位 relative 和固定定位 fixed 的結合。元素固定的相對偏移是相對于離它最近的具有滾動框的祖先元素,如果祖先元素都不可以滾動,那么是相對于 viewport 來計算元素的偏移量。 |
2. 標準文檔流
我們先來看下標準文檔流的定義:
所謂標準文檔流,指的是在不使用其他與排列和定位相關的特殊 CSS 規則時,元素的默認排列規則。
理解完定義之后,我們來看看各個取值的使用效果。
3. 各取值解析
(1)static
static ,是默認的 position 值。它沒有特殊的定位,且遵循標準文檔流。我們用例子來展示一下。
先附上代碼:
<!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>static</title> </head> <style>div{width: 100px;height: 100px;margin: 40px auto;}.one{background-color: #99d98c;}.two{background-color: #76c893;} </style> <body><div class="one"></div><div class="two"></div> </body> </html>現在來看演示效果:
大家可以看到,正如我們所想的,規規矩矩的出現在我們面前,跟我們平常實現其他內容所遵循的規則也基本一樣。所以這里不做過多解釋。
(2)relative
relative ,對象遵循標準文檔流,依賴 top,right,bottom,left 等屬性相對于該對象在標準文檔流中的位置進行偏移,同時可通過 z-index 定義層疊關系。我們現在用一個例子來展示一下。
先附上代碼:
<!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>relative</title> </head> <style>body{margin: 0 300px;}div{width: 200px;height: 200px;padding: 20px;}.one{background-color: #99d98c;position: relative;left: 40px;top: 60px;}.two{background-color: #76c893;} </style> <body><div class="one">1</div><div class="two">2</div> </body> </html>現在來看演示效果:
大家可以看到, relative 是相對于該對象所處的標準文檔流中的位置,依據 left 和 top 進行定位(當然也可以使用 right 和 bottom ,本例僅用以上兩個屬性做說明)。同時, left 和 top 并不會改變該對象原本在文檔流中的占位空間。
值得注意的是,如果設置為 margin 和 padding 屬性時,該對象在標準文檔流中的占位空間也將會隨之改變。
附上代碼:
<!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>relative</title> </head> <style>body{margin: 0 300px;}div{width: 200px;height: 200px;padding: 20px;}.one{background-color: #99d98c;position: relative;left: 40px;top: 60px;margin: 0 0 60px 40px;}.two{background-color: #76c893;} </style> <body><div class="one">1</div><div class="two">2</div> </body> </html>現在我們來看下瀏覽器的演示效果:
大家可以看到,當設置了 margin 屬性時,該對象仍然跟隨著其所處的標準文檔流中的占位空間的變化而變化。
(3)absolute
absolute ,對象脫離標準文檔流,使用 top , right , bottom , left 等屬性進行絕對定位(相對于 static 定位以外的第一個父元素進行絕對定位) ,以及可通過 z-index 定義層疊關系。
先來看個例子,具體代碼如下:
<!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> </head> <style>body{margin: 50px 300px;}.father-ele{width: 300px;height: 300px;background-color: #168aad;position: relative;}.son-ele{width: 200px;height: 200px;position: static;background-color: #76c893;margin-left: 20px;}.three{width: 100px;height: 100px;background-color: #99d98c;}.four{width: 100px;height: 100px;position: absolute;left: 0;top: 0;background-color: #b5e48c;} </style> <body><div class="father-ele">1<div class="son-ele">2<div class="three">3</div><div class="four">4</div></div></div> </body> </html>具體效果如下:
從上面的定義中我們了解到,絕對定位 absolute 是脫離標準文檔流的,且是相對于 static 定位以外第一個父元素,并且使用 left和top 或 right和bottom 進行絕對定位。所以大家可以看到上圖,設置了 absolute 的 four 相對于 father-ele 進行定位。
值得一提的是,在使用 absolute 絕對定位時,必須指定 left 、 top 、 right 和 bottom 中的至少一個,否則 left/right/top/bottom 屬性將會使用默認值 auto 。這將導致對象遵從標準文檔流,在前一個對象之后立即被呈遞,簡單講就是都變成 relative ,并且會占用文檔空間。
還有就是,如果同時設置了 left/right 屬性,那么 left 生效。同理如果 top/bottom 同時存在時, top 生效。
(4)fixed
fixed ,對象脫離標準文檔流,使用 top , right , bottom , left 等屬性進行絕對定位(相對于瀏覽器窗口進行絕對定位)同時可通過 z-index 定義層疊關系。
先來看個例子,具體代碼如下:
<!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>fixed</title> </head> <style>body{margin: 50px 300px;}.father-ele{width: 300px;height: 300px;background-color: #168aad;position: relative;}.son-ele{width: 200px;height: 200px;position: static;background-color: #76c893;margin-left: 200px;}.three{width: 100px;height: 100px;position: fixed;left: 20px;top: 20px;background-color: #99d98c;}.four{width: 100px;height: 100px;background-color: #b5e48c;} </style> <body><div class="father-ele">1<div class="son-ele">2<div class="three">3</div><div class="four">4</div></div></div> </body> </html>具體效果如下:
大家可以看到,fixed 是相對于瀏覽器窗口進行固定定位的。
(5)sticky
對于 sticky 來說,就是粘性定位,主要用來做導航欄滑動到一定程度時讓導航欄固定到頂部。不過這個屬性有它一定的利弊存在,要了解清楚其中存在的各種問題后,謹慎使用!!
這里不再過多介紹,感興趣的小伙伴可以戳此鏈接查看該屬性的內容~
講到這里,關于 position 的各種取值解析基本就結束啦!但是細心的小伙伴可能已經發現,上面一直提到的 z-index ,好像都沒有講到。不著急,接下來我們就來講講 z-index 這個屬性的紙短情長。
🍹三、z-index
1. 一個片面的理解
在我的認知里,一直認為 z-index 是用來描述頁面的層疊順序。一旦 z-index 的值越大,頁面就可以疊放的越高。但事實證明,是我孤陋寡聞了。所謂 z-index ,只有在以下場景適用。分別為:
- 首先, z-index 這個屬性并不是在所有的元素上都有效果。它僅僅只在定位元素(定義了 position 屬性,且屬性的值為非 static 值的元素)上有效果。
- 要判斷元素在 z軸 上的堆疊順序,并不僅僅是直接比較兩個元素的 z-index 值的大小,同時,這個堆疊順序還由元素的層疊上下文和層疊等級共同決定。
先來看一張圖👇
相信大家對三維坐標空間一定很熟悉。通常地,我們用 x軸 來表示水平位置,用 y軸 來表示垂直位置,然后用 z軸 來表示在紙面內外方向上的位置。但是呢,由于屏幕是一個二維平面,所以我們并不是真正地看到 z軸 。我們經常說的看到 z軸 ,實際上是通過透視,將元素展現在其二維空間的前面或者后面才看到的。
對 z-index 有了一個基礎的認識之后,我們來看看它的取值。
2. z-index的取值
要確定沿著這 z軸 元素是如何分布的,css 允許我們對 z-index 屬性設置3種類型的值。分別是:
- auto(自動,默認值);
- 整數(正整數/負整數/0);
- inherit(繼承)。
目前,讓我們先關注在整數值上。 整數值可以是正值,負值,或0。通常來說,數值越大,元素也就越靠近觀察者;而數值越小,元素看起來也就越遠。
所以,如果有兩個元素放在了一起,占據了二維平面上一塊共同的區域,那么有著較大 z-index 值的元素就會掩蓋或者阻隔有著較低 z-index 值的元素在共同區域的那一部分。
盡管如此,現在還是有一些問題懸而未決、等待我們的解答。具體問題如下:
- 當一個設置了 z-index 值的定位元素與常規文檔流中的元素相互重疊的時候,誰會被置于上方?
- 當定位元素與浮動元素相互重疊的時候,誰會被置于上方?
- 當定位元素被嵌套在其他定位元素中時,又會發生什么呢?
帶著這些問題,我們繼續深入了解神奇的 z-index 是怎么工作的,又會拋出哪些新的內容呢?
接下來我們來了解一下上述中提到的層疊上下文、層疊等級和層疊順序。
3. 層疊上下文
(1)舉個例子
我們來做一個具象的比喻:
假設現在有一張桌子,桌子上面呢,放了好多水果,那么這張桌子就代表著一個層疊上下文。
再來,我們還有一張桌子,桌子上面,放了很多本書,那么新的這張桌子,又代表著一個新的層疊上下文。
而水果和書這兩樣東西,就可以理解為他們所處的層疊上下文中的層疊上下文元素。
這樣理解,會不會就明白了許多呢。現在,我們來拋出它的定義。
(2)定義
層疊上下文(stacking context),是HTML中一個三維的概念。在 CSS2.1 規范中,每個盒模型的位置是三維的,分別是平面畫布上的X軸,Y軸以及表示層疊的Z軸。一般情況下,元素在頁面上沿 X軸 和 Y軸 平鋪,我們是察覺不到它們在Z軸上的層疊關系。而一旦元素發生堆疊,這時就能發現某個元素可能覆蓋了另一個元素或者被另一個元素覆蓋。
如果一個元素含有層疊上下文,(也就是說它是層疊上下文元素),我們可以理解為這個元素在Z軸上就“高人一等”,最終表現就是它離屏幕觀察者更近。
4. 層疊等級
(1)定義
講完層疊上下文,我們再來看看層疊等級又是什么呢?
所謂層疊等級(stacking level),也叫 層疊級別 或 層疊水平 。它有兩層含義:
- 在同一個層疊上下文中,它描述的是該層疊上下文中的層疊上下文元素在 Z軸 上的上下順序。
- 在其他普通元素中,它描述的是這些普通元素在 Z軸 上的上下順序。
(2)舉個例子
同樣,我們用剛剛那個例子來繼續舉例。假設桌子上面的蘋果和書,是一層一層疊上去的。
現在,我們先看第一張桌子,第一張桌子的所有蘋果,是在同一個層疊上下文中,那么蘋果的堆疊順序,就是在這個層疊上下文中 z軸 上的上下順序,這是第一層含義。
然后呢,第一張桌子和第二張桌子,他們是兩個不同的層疊上下文,我們把它們視為兩個普通的元素。那這兩個普通的元素,它們也有在 z軸 上的上下順序。所以呢,這個上下的堆疊順序,就是我們所說的第二層含義。
5. 形成的條件
看完層疊上下文和層疊等級,我們現在需要來了解一下,要怎么樣,才能讓元素形成層疊上下文。具體有以下幾種情況:
- 根元素html ;
- 絕對定位 ansolute 或相對定位 relative 且 z-index 值不為 auto ;
- 一個 flex 項目,且 z-index 值不為 auto ,也就是父元素 display: flex|inline-flex ;
- 元素的 opacity 屬性值小于 1 ;
- 元素的 transform 屬性值不為 none ;
- 元素的 mix-blend-mode 屬性值不為 normal ;
- 元素的 isolation 屬性被設置為 isolate ;
- 在 mobile WebKit 和 Chrome 22+ 內核的瀏覽器中,position: fixed 時總是會創建一個新的層疊上下文, 即使 z-index 的值是 auto ;
- 元素的 -webkit-overflow-scrolling 屬性被設置 touch 。
6. 層疊順序
在第 4 點中,盡管上面所說的只包含一個兩級的層疊,但事實上在一個層疊上下文中,一共可以有7種層疊等級。具體如下圖:
下面我們來一一對上面的7種層疊順序進行闡述。說明如下:
- 背景和邊框 —— 形成層疊上下文的元素的背景和邊框,也是層疊上下文中的最低等級。
- 負z-index值 —— 層疊上下文內有著 負z-index值 的子元素。
- 塊級盒 —— 文檔流中非行內非定位子元素。
- 浮動盒 —— 非定位浮動元素。
- 行內盒 —— 文檔流中行內級別非定位子元素。
- z-index: 0 —— 定位元素,這些元素將形成了新的層疊上下文。
- 正z-index值 —— 定位元素。 層疊上下文中的最高等級。
注: 字體顏色對應框內顏色
以上這七個層疊等級構成了層疊次序的規則。比如, 在層疊等級七上的元素會比在等級一至六上的元素顯示得更上方(更靠近觀察者)。 在層疊等級四上的元素會顯示在等級一至三上的元素之上。
看到上面這張圖的時候,我想到了一些坑。
如果你只看層疊等級 2 , 6 , 7 (也就是那些提到了 z-index 的等級),那么有很大的可能你會發現這跟你理解的 z-index 可能是一樣的。 正 z-index 值比 z-index:0 值更高一層, z-index:0 值又比負 z-index 值高一層。 往往我們很多時候都只理解到了這里,也就覺得 z-index 只有這些內容,往后的事也不了了之了。
但事實上,事實與現實總是不相符的。一般來說,大多數的元素都比 z-index:0 和 z-index > 0 時的層疊等級要低。
另外同樣有趣的是非定位元素分散在四個不同的層疊等級上,為什么是這樣子的呢?其實,你可以想象以下,如果所有的非定位元素都在同一層疊等級上,那么我們也就不會看到文字(行內盒)在 div 盒子上了(塊級盒)。
7. 例子展示
講到這里,相信大家對 z-index 已經有了一定的認知。接下來呢,我們就就來用一個例子鞏固一下上面所學到的知識🌈
先附上代碼:
<!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><link rel="stylesheet" href="09.scss"> </head> <style>div {width: 200px;height: 200px;padding: 20px; }.ele1, .ele2, .ele3, .ele4 {position: absolute; }.ele1 {background: #38a3a5;top: 100px;left: 200px;z-index: 10; }.ele2 {background: #99d98c;top: 50px;left: 75px;z-index: 100; }.ele3 {background: #57cc99;top: 125px;left: 25px;z-index: 150; }.ele4 {background: #80ed99;top: 200px;left: 350px;z-index: 50; } </style> <body><div class="ele1">1<div class="ele2">2</div><div class="ele3">3</div></div><div class="ele4">4</div> </body> </html>大家可以先想象一下具體的層疊順序,然后再來看結果。接下來看一下演示效果:
不知道最終的結果是都跟小伙伴們心里的預期是一樣的呢。很多小伙伴可能想著, ele4 的 z-index 值不是 50 嗎,而 ele2 和 ele3 的 z-index 值是 100 和 200 ,為什么反而是 ele4 在最上面呢。我們來解決這個疑惑。
其實, ele1 和 ele4 是兩個不同的層疊上下文,而 ele2 和 ele3 是 ele1 的層疊上下文元素。所以, ele1 的值是 10 ,而 ele2 和 ele3 可以理解為是 10.100 和 10.150 ,這樣,自然地,ele4 肯定就是在最上方了。
還有另外一種特殊情況就是, ele4 的 z-index 的值跟 ele1 的值是一樣的,都是 10 。在這種情況下,如果遇到在同一個層疊上下文的元素,他們的 z-index 值如果一樣的話,那得遵循個先來后到原則。 ele1 先出現了,所以它在里面;而 ele4 后出現,它在外面。
那如果遇到 ele4 的 z-index 的值是 9 呢?我們改一下 ele4 的 css 樣式,然后來觀察一下效果。具體代碼如下:
.ele4 {background: #80ed99;top: 200px;z-index: 9; }具體效果如下:
通過上圖,大家可以發現,ele4 的 z-index 值比 ele1 小,所以自然地, ele4 在里面, ele1 在外面。
🥂四、結束語
當你初次遇到 z-index 時,它就像一個非常簡單、易于理解的屬性。 它的值代表著在朝向屏幕內外面軸上的位置。而深入探究 z-index 以后我們還發現了很多 z-index 背后的事情, 包括層疊上下文、層疊等級和層疊次序規則等等。
所以說呀,萬宗不變其一,萬事萬物還是得追溯到源頭上才能更好的解決問題本身。
相信通過上文的了解,大家對 position 和 z-index 又有了一個全新的認識~
🐣彩蛋 One More Thing
(:參考資料
長安曹公子👉徹底搞懂CSS層疊上下文、層疊等級、層疊順序、z-index
Steven Bradley👉關于z-index 那些你不知道的事
貓兒不熊👉CSS-position:static/relative/absolute/fixed定位
書籍👉張鑫旭老師的CSS世界
(:番外篇
-
關注公眾號星期一研究室,第一時間關注優質文章,更多精選專欄待你解鎖~
-
如果這篇文章對你有用,記得留個腳印jio再走哦~
-
以上就是本文的全部內容!我們下期見!👋👋👋
總結
以上是生活随笔為你收集整理的你可能对position和z-index有一些误解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 富硒葡萄的功效与作用、禁忌和食用方法
- 下一篇: 中医可以减肥吗