你不知道的 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 布局能力。


相关推荐
前端小小王12 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发21 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀44 分钟前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6413 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云4 小时前
npm淘宝镜像
前端·npm·node.js
dz88i84 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook