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

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

我们假定用户正面向(浏览器)视窗或网页,而 HTML 元素沿着其相对于用户的一条虚构的 z 轴排开,层叠上下文就是对这些 HTML
元素的一个三维构想。众 HTML 元素基于其元素属性按照优先级顺序占据这个空间。

层叠上下文 在本篇之前的部分——运用 z-index,(我们认识到)某些元素的渲染顺序是由其 z-index
的值影响的。这是因为这些元素具有能够使他们形成一个层叠上下文的特殊属性。

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

正文

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

在这里插入图片描述

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

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

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

<body>
  <div class="container">
    <div class="item"></div>
  </div>
</body>
.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 这个盒子的层叠顺序是什么? image-20220814223451349
相信看完上面的描述,你能够很自信的回答这个简单的问题,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 布局能力。


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值