CSS堆疊上下文(The stacking context)

1. 堆疊順序

堆疊順序(stacking order):HTML 內(nèi)元素發(fā)生層疊的時(shí)候的特定垂直順序,即元素在用戶視線方向上的順序煤辨。


一般而言峦失,div 以內(nèi)在層疊順序上對于視覺有影響的一般有以下幾個(gè):

  • background
  • border
  • 塊級元素
  • 內(nèi)聯(lián)元素
  • 浮動塊級元素
  • 定位塊級元素

接下來一也,我們一個(gè)一個(gè)來測試一下他們的堆疊順序辰企。

1. 首先谓媒,測試一下 background 和 border 的堆疊順序。

在日常寫頁面中此再,很大可能是這樣的:

HTML
<body>
  <div class="parent"></div>
</body>
CSS
.parent{
  height:40px;
  border:10px solid rgba(255,0,0,1);
  background:#000;
}
image.png

一個(gè) div 元素內(nèi)有一個(gè) background 和一個(gè) border昔搂,它們兩者是分開的嗎?
現(xiàn)在输拇,將該 div 的 border 顏色改為半透明

.parent{
  height:40px;
  border:10px solid rgba(255,0,0,0.4);
  background:#000;
}

image.png

從頁面效果摘符,可以很明顯地看出來,border 的顏色并不是純種的紅色策吠,而是紅色之中透著黑色议慰。
顯而易見,border 之中的黑色就是 div 元素的background奴曙。
由上面可以推斷得出别凹,border 的堆疊順序是比 background 要高的。即 border > background


2. 接下來洽糟,給 div 加一個(gè)內(nèi)聯(lián)元素和一個(gè)塊級元素

HTML
<body>
  <div class="parent">
    <span>內(nèi)聯(lián)元素</span>
    <div class="child"></div>
  </div>
</body>
CSS
.parent{
  height:150px;
  border:10px solid rgba(255,0,0,1);
  background:#000;
}
span{
  color:#fff;
}
.child{
  width:80px;
 height:50px;
 background:green;
}
顯示效果
image.png

從上圖可以看出來炉菲,內(nèi)聯(lián)元素和塊級元素的堆疊順序都是大于 background 的堕战,那么他們與 border 相比較呢?
想辦法把這兩個(gè)元素移動到與 border 相覆蓋拍霜,就可以知道他們的堆疊順序嘱丢。
往兩個(gè)元素上分別加一個(gè) margin-left:-10px;

CSS
.parent{
  height:150px;
  border:10px solid rgba(255,0,0,1);
  background:#000;
}
span{
  color:#fff;
  margin-left:-10px;
}
.child{
  width:80px;
 height:50px;
 background:green;
 margin-left:-10px;
}
顯示效果
image.png

可以知道,內(nèi)聯(lián)元素和塊級元素的堆疊順序都大于 border 的堆疊順序祠饺。那么這兩者之間的堆疊順序呢越驻?
再往塊級元素上加一個(gè) margin-top:-10px;

CSS
.parent{
  height:150px;
  border:10px solid rgba(255,0,0,1);
  background:#000;
}
span{
  color:#fff;
  margin-left:-10px;
}
.child{
  width:80px;
 height:50px;
 background:green;
 margin-left:-10px;
  margin-top:-10px;
}
顯示效果

image.png

從上圖可以看到,綠色背景的塊級元素向上移動 10px道偷,但是內(nèi)聯(lián)元素依然在塊級元素上面缀旁,說明內(nèi)聯(lián)元素的堆疊順序大于塊級元素的內(nèi)聯(lián)順序,即 內(nèi)聯(lián)元素 > 塊級元素 > border > background勺鸦。


3. 接下來該比較一下浮動元素了

先加一個(gè)浮動元素并巍,背景色為藍(lán)色。

HTML
<body>
  <div class="parent">
    <span>內(nèi)聯(lián)元素</span>
    <div class="child"></div>
    <div class="float"></div>
  </div>
</body>
CSS
.float{
  width:80px;
  height:50px;
  background:blue;
  float:left;
}
顯示效果
image.png

現(xiàn)在换途,先測試一次懊渡,藍(lán)色的浮動元素與目前已知的最高級的內(nèi)聯(lián)元素哪個(gè)堆疊順序比較大。給浮動元素加一個(gè)margin-top:-60px;

.float{
  width:80px;
  height:50px;
  background:blue;
  float:left;
  margin-top: -60px;
}

image.png

由上圖可以知道军拟,內(nèi)聯(lián)元素在浮動元素上面剃执,所以內(nèi)聯(lián)元素的堆疊順序比浮動元素大,而浮動元素又在塊級元素上面懈息,所以浮動元素的堆疊順序大于塊級元素肾档。即 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background


4. 接下來是定位(position:relative;和position:absolute;)元素

依然是加一個(gè)定位元素

HTML
<body>
  <div class="parent">
    <span>內(nèi)聯(lián)元素</span>
    <div class="child"></div>
    <div class="float"></div>
    <div class="relative"></div>
  </div>
</body>
CSS
.relative{
  width:70px;
  height:50px;
  background:yellow;
  position:relative;
}
顯示效果
image.png

依然是加margin-top:-50px;

.relative{
  width:70px;
  height:50px;
  background:yellow;
  position:relative;
  margin-top:-50px;
}
image.png

可以看到漓拾,position:relative; 的元素直接蓋住了目前已知最高等級的內(nèi)聯(lián)元素,說明 position:relative; 的元素的堆疊順序比內(nèi)聯(lián)元素的要大戒祠。
接下來看一下 position:absolute; 將上面 position:relative; 改為 position:absolute;

.relative{
  width:70px;
  height:50px;
  background:yellow;
  position:absolute;
  margin-top:-50px;
}
image.png

從圖片可以看出結(jié)果是一摸一樣的骇两,說明 position:relative和 position:absolute; 有一樣的堆疊順序。
所以:定位元素 > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background

5. 最后是 z-index 的影響

首先要知道姜盈,z-index 生效的前提是該元素是 position 屬性值是非static的元素低千,此時(shí)的 z-index為 auto。再添加一個(gè)元素馏颂,使它的 z-index生效

HTML
<body>
  <div class="parent">
    <span>內(nèi)聯(lián)元素</span>
    <div class="child"></div>
    <div class="float"></div>
    <div class="relative"></div>
    <div class="z-index"></div>
  </div>
</body>
CSS
.z-index{
  width:90px;
  height:50px;
  background:orange;
  position:absolute;
  z-index:1;
}
顯示效果
image.png

接下來示血,繼續(xù)給一個(gè)margin-top:-40px;

.z-index{
  width:90px;
  height:50px;
  background:orange;
  position:absolute;
  z-index:1;
  margin-top: -40px;
}

image.png

可以看到橙色的加了 z-index 的元素蓋住了定位元素,說明: 正z-index > 定位元素 > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background救拉。
現(xiàn)在測試一下負(fù)z-index难审,將z-index:1;改為 z-index:-1;

.z-index{
  width:90px;
  height:50px;
  background:orange;
  position:absolute;
  z-index:-1;
  margin-top:-40px;
}
image.png

可以看到,橙色元素完全被蓋住了亿絮。
修改一下margin告喊,試著讓它顯示出來麸拄。

.z-index{
  width:90px;
  height:50px;
  background:orange;
  position:absolute;
  z-index:-1;
  margin-top:0px;
}
image.png

可以看到,即使不加margin負(fù)值黔姜,依然看不到拢切。
設(shè)置margin-top:70px;

.z-index{
  width:90px;
  height:50px;
  background:orange;
  position:absolute;
  z-index:-1;
  margin-top:70px;
}
image.png

可以看到,橙色有一部分被背景蓋住了秆吵,說明:

正z-index > 浮動元素 > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background > 負(fù)z-index

綜合上面所有內(nèi)容淮椰,元素的堆疊順序就出來了。
就是下面這個(gè):

正z-index > 浮動元素 > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background > 負(fù)z-index

上面的順序纳寂,越大的離用戶越近主穗。

2. 堆疊上下文

堆疊上下文:stacking context,類似與作用域烈疚,由不同的CSS屬性造成的一類具有相同特征的東西黔牵,并沒有特定的概念。堆疊上下文影響的是元素 CSS 屬性中的 z-index爷肝,父元素是否是堆疊上下文猾浦,對具有z-index屬性的子元素的堆疊順序有影響。

文檔中的層疊上下文由滿足以下任意一個(gè)條件的元素形成:

  • 根元素 (HTML),
  • z-index 值不為 "auto"的 絕對/相對定位灯抛,
  • 一個(gè) z-index 值不為 "auto"的 flex 項(xiàng)目 (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"的元素

接下來看一下堆疊上下文對 z-index 的影響:
首先創(chuàng)建一個(gè)父元素的 div 作為容器靡砌,然后添加兩個(gè)子 div 已脓,兩個(gè)子 div 里分別添加一個(gè)子 div

HTML
<body>
  <div class="parent">
    <div class="a relative">
      <div class="aaa">aaa</div>
    </div>
    <div class="b relative">
      <div class="bbb">bbb</div>
    </div>
  </div>
</body>

接下來,使用 CSS 添加樣式通殃,此時(shí)頁面內(nèi)有一個(gè)堆疊上下文=》html 元素

CSS
.parent{
  height:200px;
  border:10px solid red;
  background:black;
  padding:10px;
}

.a,.b{
  border:1px solid red;
  width:200px;
  height:100px;
  background:green;
}

.aaa,.bbb{
  background:yellow;
}

.relative{
  position:relative;
}
顯示效果
image.png

接下來給 bbb 添加一個(gè) z-index:1;并使它移動到 aaa 的位置度液。

.bbb{
  z-index:1;
  margin-top:-90px;
}

image.png

可以看到 bbb 蓋住了 aaa ,因?yàn)?bbb 的 z-index:1; 比 aaa 默認(rèn)的 z-index:auto;更靠近用戶画舌。說明 在同一個(gè)堆疊上下文中堕担,z-index大的比z-index小的更靠近用戶
接下來使 a 和 b 形成堆疊上下文

.a,.b{
  border:1px solid red;
  width:200px;
  height:100px;
  background:green;
  z-index:0;
}
image.png

頁面并沒有變化,那么這時(shí)候修改一下 aaa 和 bbb 的z-index 大小呢曲聂?將 aaa 的 z-index 改為2

.aaa{
  z-index:2;
}

image.png

頁面依然沒有變化霹购,說明不同堆疊上下文中,z-index的大小不會影響到元素的堆疊順序朋腋,此時(shí)的堆疊順序與堆疊上下文所屬元素的堆疊順序有關(guān)厕鹃。

接下來讓 parent 元素形成堆疊上下文,并給 a 和 b 一個(gè)負(fù)z-index

.parent{
  height:200px;
  border:10px solid red;
  background:black;
  padding:10px;
  position:relative;
  z-index:0;
}

.a,.b{
  border:1px solid red;
  width:200px;
  height:100px;
  background:green;
  
}

.aaa,.bbb{
  background:yellow;
}

.relative{
  position:relative;
  z-index:-1;
  margin-top:50px;
}

image.png

可以看到兢仰,a 和 b 蓋住了 border,說明堆疊上下文中剂碴,負(fù)z-index > border把将。可以看作是堆疊上下文將所有元素包裹了起來,不允許有比堆疊上下文低的堆疊順序忆矛。


3. 總結(jié)

  1. 普通塊級元素中察蹲,z軸元素的堆疊順序如下:
    正z-index > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > border > background >負(fù)z-index
  2. 堆疊上下文中,z軸元素的堆疊順序如下:
    正z-index > 內(nèi)聯(lián)元素 > 浮動元素 > 塊級元素 > 負(fù)z-index > border > background
  3. z軸順序遵循兩個(gè)原則:
  • 誰大誰上
  • 大小一樣催训,后來居上

部分參考自:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洽议,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子漫拭,更是在濱河造成了極大的恐慌亚兄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件采驻,死亡現(xiàn)場離奇詭異审胚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)礼旅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門膳叨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痘系,你說我怎么就攤上這事菲嘴。” “怎么了汰翠?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵龄坪,是天一觀的道長。 經(jīng)常有香客問我复唤,道長健田,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任苟穆,我火速辦了婚禮抄课,結(jié)果婚禮上唱星,老公的妹妹穿的比我還像新娘雳旅。我一直安慰自己,他們只是感情好间聊,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布攒盈。 她就那樣靜靜地躺著,像睡著了一般哎榴。 火紅的嫁衣襯著肌膚如雪型豁。 梳的紋絲不亂的頭發(fā)上僵蛛,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音迎变,去河邊找鬼充尉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛衣形,可吹牛的內(nèi)容都是我干的驼侠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼谆吴,長吁一口氣:“原來是場噩夢啊……” “哼倒源!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起句狼,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤笋熬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后腻菇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胳螟,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年芜繁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旺隙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骏令,死狀恐怖蔬捷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榔袋,我是刑警寧澤周拐,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站凰兑,受9級特大地震影響妥粟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吏够,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一勾给、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锅知,春花似錦播急、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昌妹,卻和暖如春捶枢,著一層夾襖步出監(jiān)牢的瞬間握截,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工烂叔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谨胞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓蒜鸡,卻偏偏與公主長得像畜眨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子术瓮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359