深入理解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来控制整体的堆叠顺序。这种方法减少了单独管理每个元素所需的图层数量,从而降低了渲染复杂度,提高了性能。

相关推荐
康一夏3 小时前
CSS盒模型(Box Model) 原理
前端·css
炫饭第一名3 小时前
Lottie-web 源码解析(一):从 JSON Schema 认识 Lottie 动画的本质📒
前端·javascript·css
be or not to be4 小时前
Html-CSS动画
前端·css·html
@Autowire5 小时前
Grid-grid-template-areas 属性
前端·javascript·css
吴敬悦19 小时前
我被 border-image 坑了一天,总算解决了
css
ashcn20011 天前
水滴按钮解析
前端·javascript·css
Java陈序员1 天前
告别手写礼簿!一款开源免费的电子红白喜事礼簿系统!
javascript·css·html
winfredzhang1 天前
从零构建:基于 Node.js 的全栈视频资料管理系统开发实录
css·node.js·html·音视频·js·收藏,搜索,缩略图
加个鸡腿儿2 天前
经验分享2:SSR 项目中响应式组件的闪动陷阱与修复实践
前端·css·架构
华仔啊2 天前
写 CSS 用 px?这 3 个单位能让页面自动适配屏幕
前端·css