深入理解CSS层叠上下文与z-index🤓👆

层叠上下文

假设页面是三维立体的,那么用户就是正对着观测页面(浏览器),而HTML元素就可以沿着那条虚构的z轴叠加。层叠上下文就是对这些HTML元素的三维构想。而HTML通过特定的属性来占据z轴更上方的位置,以此来确定它们的堆叠顺序。

当然并非所有元素都能形成新的层叠上下文,必须是满足特定条件的元素才可以。(例如:含非autoz-index值)

创建层叠上下文的前提条件:

  • 元素的position属性设置为relativeabsolutefixedsticky
  • 元素使用了某些特定CSS属性,如 opacity 小于 1, transform 不是 none 等。

z-index属性

z-index属性在css中用于控制元素在z轴(即垂直于页面的方向)上的堆叠顺序,而在默认情况下,所有HTML元素位于同一个层叠上下文中,并且z-index属性默认为auto,这样它们均位于默认的切面上(即不参与特定层叠上下文的堆叠顺序)。

不妨来看个具体的例子:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>层叠上下文</title>
    <style>
        .box1 {
            position: absolute;
            top: 20px;
            left: 20px;
            width: 100px;
            height: 100px;
            background-color: red;
            z-index: 1;
        }
        .box2 {
            position: absolute;
            top: 40px;
            left: 40px;
            width: 100px;
            height: 100px;
            background-color: blue;
            z-index: 2;
        }
    </style>
</head>
<body>
    <div class="box1">box1</div>
    <div class="box2">box2</div>
</body>
</html>

由于box2z-index属性值要大于box1的,所以box1box2覆盖了,最终呈现的效果如图

层叠上下文的父子关系:

在对层叠上下文和z-index有所了解后,不妨来看一个比较奇特的样例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            padding: 20px;
        }
        div {
            width: 100px;
            height: 100px;
            position: relative;
        }
        .box1 {
            z-index: 2;
        }
        .box2 {
            z-index: 1;
        }
        p {
            opacity: 0.7;
            position: absolute;
            font-size: 20px;
            width: 100px;
            height: 100px;
        }
        .a {
            opacity: 1;
            border: 1px dashed #009;
            background-color:#ddf;
            z-index: 1; 
        }
        .b {
            border: 1px dashed #696;
            background-color: #cfc;
            top: 20px;
            left: 20px;
            z-index: 2;
        }
        .c {
            border: 1px dashed #900;
            background-color: #fdd;
            top: -20px;
            left: 40px;
            z-index: 9;
        }
    </style>
</head>
<body>
    <div class="box1">
        <p class="a">a</p>
        <p class="b">b</p>
    </div>
    <div class="box2">
        <p class="c">c</p>
    </div>
</body>
</html>

最终呈现的样式为:


分析:

body部分

html 复制代码
<div class="box1">
    <p class="a">a</p>
    <p class="b">b</p>
</div>
<div class="box2">
    <p class="c">c</p>
</div>

abbox1的子元素,cbox2的子元素。

css部分

抛开其他样式,我们主要观察这些元素的z-index属性值。

css 复制代码
.box1 ->  z-index: 2;
.box2 ->  z-index: 1;
.a    ->  z-index: 1; // 蓝色
.b    ->  z-index: 2; // 绿色
.c    ->  z-index: 9;// 红色

由于每个元素都被指定了定位属性和z-index值,所以它们都创建了独自的层叠上下文。不妨先将层叠上下文的层级列在下方:

  • html
    • box1
      • a
      • b
    • box2
      • c

先分析兄弟元素box1box2,这俩个元素是位于同一层叠上下文,比较其z-index值大小即可确定box2被渲染在box1的下方。而ab位于box1的子级层叠上下文中,c位于box2的子级层叠上下文中。

但是并非z-index值越大就一定在越上方,因为z-index只体现在自身位于的层叠上下文中,所以即使cz-index值很大,但是也仅仅是在box2的层叠上下文中"称王称霸"。因为其父元素box2不够努力,只能被压在box1下,那么其子元素c也难逃被box1压在身下的命运。

分辨层叠元素的渲染顺序也很简单,可以将它们的z-index值当做编号通过"."来连接起来(就像版本号一样),把子元素当作父元素的小版本。(版本越高越后渲染)

  • html
    • box1 : z-index为 2
      • a : z-index为 2.1
      • b : z-index为 2.2
    • box2 : z-index为 1
      • c : z-index为 1.9

性能问题:过多的z-index

虽然 z-index属性是管理元素重叠的一个强大工具,但过度使用会导致性能下降,因为浏览器必须计算和维护更多的图层。

解决方案:父图层管理子图层

将相关的元素放在同一个父容器内,并通过设置该父容器的z-index来控制整体的堆叠顺序。这种方法减少了单独管理每个元素所需的图层数量,从而降低了渲染复杂度,提高了性能。

相关推荐
天外来物2 小时前
element-plus主题配置及动态切换主题
前端·css·element
b***748810 小时前
前端CSS预处理器对比,Sass与Less
前端·css·sass
诸葛老刘17 小时前
前端 css中的函数
前端·css
倚肆20 小时前
CSS 选择器空格使用区别详解
前端·css
盼哥PyAI实验室20 小时前
学会给网页穿衣服——学习 CSS 语言
前端·css·学习
程序猿_极客1 天前
【期末网页设计作业】HTML+CSS+JS 旅行社网站、旅游主题设计与实现(附源码)
javascript·css·html·课程设计·期末网页设计
q***58191 天前
【HTML+CSS】使用HTML与后端技术连接数据库
css·数据库·html
振华OPPO2 天前
Vue:“onMounted“ is defined but never used no-unused-vars
前端·javascript·css·vue.js·前端框架
J***Q2922 天前
前端CSS架构模式,BEM与ITCSS
前端·css
qq_398586542 天前
浏览器中内嵌一个浏览器
前端·javascript·css·css3