沐游虞笔记
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • CSS 面试题汇总
  • CSS单位总结

    • CSS单位总结
  • 居中方式总结

    • 居中方式总结
  • 隐藏元素的方式总结

    • 隐藏元素的方式总结
  • 浮动

    • 浮动
  • 定位总结

    • 定位总结
  • BFC

    • BFC
  • CSS属性的计算过程

    • CSS属性的计算过程
  • CSS层叠继承规则总结

    • CSS层叠继承规则总结
  • import指令

    • import指令
  • CSS3的calc函数

    • CSS3的calc函数
  • CSS3的媒介(media)查询

    • CSS3的媒介(media)查询
  • 过渡和动画事件

    • 过渡和动画事件
  • 渐进增强和优雅降级

    • 渐进增强和优雅降级
  • CSS3变形

    • CSS3 变形
  • 渐进式渲染

    • 渐进式渲染
  • CSS渲染性能优化

    • CSS渲染性能优化
  • 堆叠上下文

    • 层叠上下文
      • 经典真题
      • 层叠上下文
      • 层叠等级与层叠顺序
      • 实战案例
      • CSS3 中属性对层叠上下文的影响
      • 真题解答
  • CSS3 遮罩

    • CSS3 遮罩
  • CSS 面试题汇总
  • 堆叠上下文
luzhichang
2023-10-14
目录

层叠上下文

# 层叠上下文

# 经典真题

  • 请简述什么是层叠上下文、什么是层叠等级、什么是层叠顺序

# 层叠上下文

在介绍层叠上下文之前,我们先来介绍一下 HTML 文档中的三维概念。

平时我们从设备终端看到的 HTML 文档都是一个平面的,事实上 HTML 文档中的元素却是存在于三个维度中。除了大家熟悉的平面画布中的 x 轴和 y 轴,还有控制第三维度的 z 轴。

image-20211229105842101

其中 x 轴通常用来表示水平位置,y 轴来表示垂直位置,z 轴表示屏幕内外方向上的位置。

对于 x 和 y 轴我们很易于理解,一个向右,一个向下。但对于 z 轴,理解起来就较为费力。在 CSS 中要确定沿着 z 轴排列元素,表示的是用户与屏幕的这条看不见的垂直线:

image-20211229110052865

而这里我们要讨论的层叠上下文( stacking context ),就是 HTML 中的一个三维的概念。如果一个元素含有层叠上下文,我们可以理解为这个元素在 z 轴上就“高人一等”,最终表现就是它离屏幕观察者更近。

听上去好像很不错的样子,我想让一个元素更加靠前,我就给他创建一个层叠上下文。

那么具体的创建方法有哪些呢?

一般来讲有 3 种方法:

  • HTML 中的根元素 HTML 本身就具有层叠上下文,称为“根层叠上下文”。
  • 普通元素设置 position 属性为非 static 值并设置 z-index 属性为具体数值,会产生层叠上下文
  • CSS3 中的新属性也可以产生层叠上下文

赶紧试验一下:

<div class="one"></div>
<div class="two"></div>
div{
  width: 200px;
  height: 200px;
}
.one{
  background-color: red;
}
.two{
  background-color: blue;
  margin-top: -100px;
}

在上面的代码中,我们创建了两个 div,然后使其产生重叠,默认情况下后来居上,蓝色的会盖住红色的。

image-20211229110917880

下面我们给红色设置一个定位,如下:

...
.one{
  background-color: red;
  position: relative;
  z-index: 1;
}
...

由于设置了定位和 z-index 属性,所以红色的 div 就会创建一个层叠上下文,在 z 轴上就“高人一等”。

image-20211229111127835

OK,感觉很简单的样子,打完收工,撤退!

但是且慢少年,这才刚刚开始。

image-20211229112034560

# 层叠等级与层叠顺序

除了层叠上下文,我们还需要了解两个概念:

  • 层叠等级( stacking level )
  • 层叠顺序( stacking order )

这两个东西实际上都是用来表述:

在同一个层叠上下文中,元素在 z 轴上的显示顺序。

只不过前一个是概念,后一个是具体规则。

如果两个元素在同一个层叠上下文中,那么层叠等级越大的元素,就越靠前。

那么问题来了,我怎么知道该元素的层叠等级是高还是低?

所以层叠等级的高低规则是由层叠顺序来体现的。

在 CSS2.1 的年代(注意这里的前提),层叠顺序规则遵循下面这张图:

image-20210917111327410

那么如果两个元素不在同一个层叠下上文中呢?

那么此时就先比较他们所处的层叠上下文的层叠等级,也就是所谓的“从父”现象。

假设一个官员 A 是个省级领导,他下属有一个秘书 a-1,家里有一个保姆 a-2。另一个官员 B 是一个县级领导,他下属有一个秘书 b-1,家里有一个保姆 b-2。

a-1 和 b-1 虽然都是秘书,但是你想一个省级领导的秘书和一个县级领导的秘书之间有可比性么?甚至保姆 a-2 都要比秘书 b-1 的等级高得多。谁大谁小,谁高谁低一目了然,所以根本没有比较的意义。

因此只有在 A 下属的 a-1、a-2 以及 B 下属的 b-1、b-2 中相互比较大小高低才有意义。

# 实战案例

在开始实战案例之前,我们先对上面的知识进行一个总结。

  1. 首先先看要比较的两个元素是否处于同一个层叠上下文中:

    • 如果是,谁的层叠等级大,谁在上面(判断层叠等级大小参阅上面的“层叠顺序”图)

    • 如果两个元素不在同一层叠上下文中,请先比较他们所处的层叠上下文的层叠等级。

  2. 当两个元素层叠等级相同、层叠顺序相同时,在 DOM 结构中后面的元素层叠等级在前面元素之上。

接下来我们来通过几个实际的例子加深对上面概念的理解。

示例 1:

<div class="one">
  <div class="item" style="background-color: black; z-index: 99;"></div>
</div>
<div class="two">
  <div class="item" style="background-color: pink;top: 50px; z-index: 1;"></div>
</div>
div{
  width: 200px;
  height: 200px;
}
.one{
  background-color: red;
  position: relative;
  z-index: 1;
}
.two{
  background-color: blue;
  position: relative;
  z-index: 2;
}
.item{
  width: 100px;
  height: 100px;
  position: absolute;
  left: 200px;
  top: 200px;
}
image-20211229132843959

在上面的代码中,one 和 two 分别有自己的层叠上下文,但是 two 的层叠等级要比 one 高,之后我们可以看到,无论 one 中的子元素的 z-index 设置有多高,它始终被 two 的子元素给覆盖,因为如果两个元素不在同一层叠上下文中,比较的是所在层叠上下文的等级。

示例 2:

<div class="box1">
  <div class="child1"></div>
</div>

<div class="box2">
  <div class="child2"></div>
</div>
.box1,
.box2 {
  position: relative;
}

.child1 {
  width: 200px;
  height: 100px;
  background: #168bf5;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
}

.child2 {
  width: 100px;
  height: 200px;
  background: #32c292;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}
image-20210917112008034

在上面的示例中,.box1/.box2 虽然设置了 position: relative,但是在没有设置 z-index。所以 .box1/.box2 仍然是普通元素,所以 child1/.child2 属于 html 元素的“根层叠上下文”中,也就是处于同一个层叠上下文中,根据层叠顺序谁的 z-index 值大,谁在上面。

示例 3:

将上面案例中的 CSS 代码稍作修改,如下:

.box1,
.box2 {
  position: relative;
  z-index: 0;
}
image-20210917112806638

此时,我们发现,仅仅修改了 .box1/.box2 的 z-index 属性值改为数值 0,最终结果完全相反。

这时 .child2 覆盖在了 .child1 上面。原因是什么呢?

很简单:因为设置 z-index: 0 后,.box1/.box2 产生了各自的层叠上下文,这时候要比较 .child1/.child2 的层叠关系属于不同的层叠上下文进行比较,此时由由各自所在的 .box1/.box2 的层叠等级来决定。

但是 .box1/.box2 的 z-index 值都为 0,都是块级元素(所以它们的层叠等级,层叠顺序是相同的),这种情况下,在 DOM 结构中后面的覆盖前面的,所以 .child2 就在上面。

示例 4:

<div class="box">
  <img src="./ok.png" alt="" class="item">
</div>
.box{
  width: 200px;
  height: 200px;
  background: blue;
  position: absolute;
}
.item{
  position: absolute;
  width: 200px;
  left: 50px;
  top: 50px;
  z-index: -1;
}
image-20211229134234900

在上面的代码中,.box 虽然设置了定位,但是并没有设置 z-index 属性,所以并不会产生层叠上下文,仅仅是一个普通元素,此时 .item 图片属于 html 元素的“根层叠上下文”中,根据层叠顺序谁的 z-index 值大,谁在上面。

示例 5:

将上面的代码稍作修改,为 .box 添加一个 z-index 属性,并且给了一个很大的值

.box{
  width: 200px;
  height: 200px;
  background: blue;
  position: relative;
  z-index: 99;
}
image-20211229141342897

此时效果就完全不一样了,明明 .box 给了一个很大的值,但是图片却在上面,这是为什么呢?

因为 当 .box 设置了 z-index 后,就会产生一个层叠上下文,也就是说对 .item 图片而言,找到的层叠上下文是 .box 而不是 html 根元素。而根据层叠顺序,background 是处于最下层的,所以图片显示在了最上面。

示例 6:

<div class="parent">
  parent
  <div class="child1">child1</div>
  <div class="child2">
    child2
    <div class="child2-1">child2-1</div>
    <div class="child2-2">child2-2</div>
  </div>
</div>
.parent {
  width: 100px;
  height: 200px;
  background: #168bf5;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
}

.child1 {
  width: 100px;
  height: 200px;
  background: #32d19c;
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 1;
}

.child2 {
  width: 100px;
  height: 200px;
  background: #e4c950;
  position: absolute;
  top: 40px;
  left: 40px;
  z-index: -1;
}

.child2-1 {
  width: 100px;
  height: 200px;
  background: #e45050;
  position: absolute;
  top: 60px;
  left: 60px;
  z-index: 9999;
}

.child2-2 {
  width: 100px;
  height: 200px;
  background: #db68a7;
  position: absolute;
  top: 80px;
  left: 40px;
  z-index: -9999;
}
image-20210917115354011

在上面的代码中,对于 .child1 和 .child2 来讲,他俩是处于同一个层叠上下文中,所以 .child1 在 .child2 的上面(因为 .child1 的 z-index 值更大),而对于 .child2-1 和 .child2-2 来讲,他俩也是处于同一个层叠上下文 .child2 里面,所以无论 .child2 的 z-index 值有多大,都一定在 .child2-1 和 .child2-2 下面,而 .child2-1 和 .child2-2 则根据 z-index 值的大小来决定谁覆盖谁。

# CSS3 中属性对层叠上下文的影响

CSS3 中出现了很多新属性,其中一些属性对层叠上下文也产生了很大的影响。如下:

  • 父元素的 display 属性值为 flex|inline-flex,子元素 z-index 属性值不为 auto 的时候,子元素为层叠上下文元素
  • 元素的 opacity 属性值不是 1
  • 元素的 transform 属性值不是 none
  • 元素 mix-blend-mode 属性值不是 normal
  • 元素的 filter 属性值不是 none
  • 元素的 isolation 属性值是 isolate
  • will-change 指定的属性值为上面任意一个
  • 元素的 -webkit-overflow-scrolling 属性值设置为 touch

CSS3 中,元素属性满足以上条件之一,就会产生层叠上下文。我们用第 1 条来做一个简单的解释说明。

<div class="box">
  <div class="parent">
    parent
    <div class="child">child</div>
  </div>
</div>
.box {
}
.parent {
  width: 200px;
  height: 100px;
  background: #168bf5;
  /* 虽然设置了z-index,但是没有设置position,z-index 无效,.parent还是普通元素,没有产生层叠上下文 */
  z-index: 1;
}

.child {
  width: 100px;
  height: 200px;
  background: #32d19c;
  position: relative;
  z-index: -1;
}

效果:

image-20210917114513631

我们发现,.child 被 .parent 覆盖了。按照之前的规则来分析一下:

虽然 .parent 设置了 z-index 属性值,但是没有设置 position 属性,z-index 无效,所以没有产生层叠上下文,仍然是一个普通的块级元素。 .child 的层叠上下文为 html 根元素,z-index 小于 0 的 .child 会被普通的 block 块级元素 .parent 覆盖。

对于上面的例子,我们只修改 .box 的属性,设置 display: flex,其余属性和 DOM 结构不变。

.box {
  display: flex;
}

效果:

image-20210917114834856

在上面的示例中,当给 .box 设置 display: flex 时,.parent 也会变成一个弹性项目,成为一个层叠上下文元素。于是对于 .child 来讲找到的层叠上下文就是 .parent 了,而非 html 根元素。

根据层叠顺序规则,层叠上下文元素的 background/border 的层叠等级小于 z-index 值小于 0 的元素的层叠等级,所以 z-index 值为 -1 的*.child* 在 .parent 上面。

# 真题解答

  • 请简述什么是层叠上下文、什么是层叠等级、什么是层叠顺序

层叠上下文概念

在 CSS2.1 规范中,每个盒模型的位置是三维的,分别是平面画布上的 X 轴,Y 轴以及表示层叠的 Z 轴。

一般情况下,元素在页面上沿 X 轴 Y 轴平铺,我们察觉不到它们在 Z 轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。

层叠上下文触发条件

  • HTML 中的根元素 HTML 本身就具有层叠上下文,称为“根层叠上下文”。
  • 普通元素设置 position 属性为非 static 值并设置 z-index 属性为具体数值,产生层叠上下文
  • CSS3 中的新属性也可以产生层叠上下文

层叠等级

如果两个元素在同一个层叠上下文中,那么层叠等级越大的元素,就越靠前。层叠等级是一个概念,层叠等级的大小可以根据层叠顺序来进行判断。

层叠顺序

层叠顺序表示元素发生层叠时按照特定的顺序规则在 Z 轴上垂直显示。

说简单一点就是当元素处于同一层叠上下文内时如何进行层叠判断。

image-20210917111327410

-EOF-

CSS渲染性能优化
CSS3 遮罩

← CSS渲染性能优化 CSS3 遮罩→

Theme by Vdoing | Copyright © 2021-2024 蜀ICP备2024068710号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式