你不知道的 CSS 之层叠上下文

不知道大家有没有听过 CSS 层叠上下文这个名词,我最近听到这个词的时候,一脸懵逼,压根就没有听说过这个名词。出于好奇心,我就在MDN里查阅了这个名词好好研究了一番,它在MDN里是这样描述的:

如果你也对层叠上下文的知识不太清楚,那么系好安全带,咱们准备出发了。

正文

层叠上下文英语全称为stacking context,实际上平时你在书写 CSS 时,大多数情况下你是感受不到它的存在,因此你不知道这个知识点也是一件很正常的事情。在MDN文档里它是这样描述的

那么,这个层叠上下文究竟说了什么内容呢? 说起来也简单,就是元素在页面上的层叠顺序,会受到它的层叠上下文所影响。 层叠上下文定义了元素如何影响其他元素的层叠顺序,以及元素在页面上的显示顺序。 我们可以把它总结为三点:

  1. 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
  2. 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
  3. 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。

让我们从最简单的 case 开始看。

html 复制代码
<body>
  <div class="container">
    <div class="item"></div>
  </div>
</body>
css 复制代码
.container{
  width: 500px;
  height: 300px;
  background-color: skyblue;
  position: relative;
}
.item{
  width: 50%;
  height: 50%;
  background-color: red;
  position: absolute;
  top: 20px;
  left: 20px;
}

请仔细阅读上面的代码,然后你认为 div.item 这个盒子的层叠顺序是什么? 相信看完上面的描述,你能够很自信的回答这个简单的问题,div.item 盒子的层叠顺序是在其父元素 .container 之上。 这个答案确实是没有问题的,但是如果我追问你是怎么得到这个答案的,我猜不了解层叠上下文的你大概率会说,因为它的父元素 div.container 的 position 为 relative,所以 div.item 的层叠顺序是在其父元素之上。 这个答案实际上是不准确的。正确的答案应该是,div.item 的层叠顺序是根据它的层叠上下文来计算的,而这里层叠上下文的大小,正是这个元素最近的祖先层叠上下文元素。这是什么意思呢?

.item 元素的层叠顺序确实受其最近的层叠上下文(即其父元素 .container)的影响。然而,对于 .item 来说,其层叠顺序不仅仅因为 .containerposition: relative 而在其之上,而是因为 .item 自身的 position: absolute 使其创建了一个新的层叠上下文。

当一个元素的定位类型为 absolutefixed,或者它具有 transform, opacity, mix-blend-mode, filter, clip-path, mask, perspective, isolation 属性设置为非默认值时,它会创建一个新的层叠上下文。.item 使用了 position: absolute,因此它创建了自己的层叠上下文。

然而,在这个例子中,.item.container 都没有显式地指定 z-index 值。在没有 z-index 的情况下,元素的层叠顺序主要由它们在文档流中的出现顺序决定。因为 .item.container 内部的HTML源码中出现在 .container 的结尾附近,所以在默认情况下,它将位于 .container 的其他内容之上,只要它没有被其他具有更高 z-index 或者在它之后出现并创建层叠上下文的元素覆盖。

虽然 .item 的层叠顺序是在 .container 之上,但这主要是因为 .item 的定位���式和在源码中的位置,而不是直接因为 .containerposition: relative。如果 .container 没有 position: relative.itemposition: absolute 也会相对于 body 或者下一个最近的具有定位属性的祖先元素创建层叠上下文。但是,.containerposition: relative 确保了 .item 相对于 .container 进行定位,而不是相对于 body 或其他元素。

因此正如我前面所说,很多时候你都感受不到层叠上下文的存在。

层叠上下文分为几种,分别是:

  1. 文档根元素(<html>);
  2. position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;
  3. position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);
  4. flex (flex) 容器的子元素,且 z-index 值不为 auto;
  5. grid (grid) 容器的子元素,且 z-index 值不为 auto;
  6. opacity 属性值小于 1 的元素(参见 the specification for opacity);
  7. mix-blend-mode 属性值不为 normal 的元素;
  8. 以下任意属性值不为 none 的元素:
    • transform
    • filter
    • backdrop-filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  9. isolation 属性值为 isolate 的元素;
  10. will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素(参考这篇文章);
  11. contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。

层叠上下文的层级关系

层叠上下文之间存在层级关系,层叠上下文由内向外,层叠顺序依次降低。这意味着内层的层叠上下文会覆盖外层的层叠上下文。

层叠上下文的应用场景

了解层叠上下文的概念对于解决实际开发中的布局问题非常有帮助。以下是一些层叠上下文在实战中的应用场景:

  1. z-index 值的影响:通过设置不同的 z-index 值,可以控制元素的层叠顺序。
  2. 定位元素与层叠上下文:了解定位元素如何创建层叠上下文,可以帮助我们更好地控制元素的显示顺序。
  3. flex 元素与层叠上下文:使用 flex 布局时,了解层叠上下文可以让我们更好地控制子元素的层叠顺序。
  4. grid 元素与层叠上下文:使用 grid 布局时,了解层叠上下文可以让我们更好地控制子元素的层叠顺序。

总结

层叠上下文是 CSS 布局中的一个重要概念,它定义了元素在页面上的层叠顺序。通过深入理解层叠上下文的工作原理,我们可以更有效地使用 CSS 属性,实现复杂而优雅的页面布局。记住,每个元素都存在于一个层叠上下文中,而这个上下文决定了元素在页面上的显示顺序。 在实际开发中,了解层叠上下文的概念对于解决布局问题非常有帮助。通过实践和不断学习,我们可以更好地掌握层叠上下文的应用技巧,提高我们的 CSS 布局能力。


相关推荐
zhougl99615 分钟前
html处理Base文件流
linux·前端·html
花花鱼19 分钟前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_22 分钟前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo2 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端3 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡3 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木4 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!5 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷5 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript