一个div 上下两行_CSS 中的层叠上下文

801ea7b467ff15b377909241ffaa3b67.png

在使用 bootstrap 的模态框时,出现了半透明遮罩始终盖住模态框的情况, 只有把模态框的 HTML 写到 body 之下才恢复正常, 当时郁闷得对着屏幕举了半分钟的中指。(程序员最好看看佛经,学会清心寡欲)

后来有幸看到了张鑫旭在慕课网 CSS深入理解之 relative 的视频, 才算真正知晓了层叠上下文在 CSS 中的规则和运用技巧。

还有些名称比较类似的学术语言和概念,格式化上下文、执行上下文、音频上下文、2D上下文等,感兴趣地可以去搜一下玩玩。

废话有些多,下面就正式开始吧!

什么是层叠上下文和层叠水平

层叠上下文其实把它理解为 z 轴也没有问题,屏幕上面叠着一层层图层(不是所有的元素都是)。层叠水平则表示同一层层叠上下文对应的图层。

创建层叠上下文

那么怎样才能产生层叠上下文,让它的 z 轴不一样呢?

以下情况会创建层叠上下文(随着 CSS3 属性还在增加,本表不全):

  • z-index 不为 auto 的 position
  • 定位元素 z-index
  • 不为 auto 的 flex
  • opacity 不为 1
  • transform 不为 none
  • perspective 不为 none
  • filter 不为 none
  • mix-blend-mode 不为 normal
  • 带有 isolation: isolate
  • will-change 不为 none
  • 带有 -webkit-overflow-scrolling: touch
<style>
.box {
  width: 100px;
  height: 100px;
  margin: 0 auto -50px;
}
.box1 {background: pink}
.box2 {background: grey}
.box1 {left: 10px}

.box1 { transform: translate(0,0) }
</style>

<div class="box box1"></div> <!-- 粉色 -->
<div class="box box2"></div> <!-- 灰色 -->

3bacf9334cec5553483c8d9d63c950eb.png
层叠上下文层级会高于普通元素

此例中 .box1 创建了层叠上下文,z 轴上就比普通元素层级更高了,因此覆盖了 .box2。

同级层叠水平下的层叠顺序

而当有两个层叠上下文时,它们就有了兄弟和父子关系(假设现在都处于同级层叠水平)。

当为兄弟关系时(层叠上下文的兄弟关系,非 DOM 的兄弟),它们总是 后者居上 的。

<style>
.box {
  width: 100px;
  height: 100px;
  margin: 0 auto -50px;
}
.item {
  /* 两个 dom 中子级创建层叠上下文,构成兄弟关系的层叠水平 */
  transform: translate(0,0);
  width: 90px;
  height: 90px;
  top: -10px;
}
.box1 {background: pink}
.box2 {background: grey}
.item1 {background: red}
.item2 {background: green}
.item1 {left: -10px;}
.item2 {left: -20px;}
</style>

<div class="box box1"> <!-- 粉色 -->
  <div class="item item1">item1</div> <!-- 红色 -->
</div>
<div class="box box2"> <!-- 灰色 -->
  <div class="item item2">item2</div> <!-- 绿色 -->
</div>

<!-- .item 变为层叠上下文,所以比 .box 这种普通元素层级更高. -->
<!-- 且 .item 遵循后者居上,所以 .item2 覆盖了 .item1 -->

90847e6c17f76ccfed9f811b95ecd7ef.png
父级皆不为层叠上下文,子级层级上为兄弟关系,会对比

当为父子关系时,子级就存在父级的“作用域”内了,父级高我才高,不然我再高也没用。

<style>
.box { position: relative; z-index: 0 }
.item1 { z-index: 999; }
/* 紧跟上例,本来 .item2 由谁后谁上的原则位于上面。 */
/* 当现在其父级 .box 也创建的层叠上下文,且遵循谁后谁上,因此 .box2 要高于 .box1。 */
/* 此处 .item1 的父级已经低于 .box2 了,本身层级再高也还是在 .box1 的范围内而已。 */
</style>

052cd67883196bf7fe458ad80839c01f.png
父级皆为层叠上下文,子级层级上为堂兄弟关系,只对比父级

注:此处 position: relative; 但不写 z-index: 0(即 z-index: auto),它会覆盖普通元素,但并不会创建层叠上下文。 下面这个也是类似的例子,

.box {
  position: relative;
  margin: 0 0 10px;
}
.box2 { z-index: 0; }
/* 只有 z-index 不为 auto 才创建层叠上下文,所以 .box2 创了,.box1 没创 */
.item {
  position: relative;
  z-index: -1;
}

bde8312b5f3e726fe6bfed53017d9de1.png
当父级为层叠上下文时,子级无法再低于父级的层级

不同级层叠水平下的层叠顺序

既 z-index 不为 auto 的情况,这时它们总是 谁大谁上 的。

<style>
.box1 { z-index: 2; }
/* 这个就很好理解了,.box 现在是兄弟关系,.box1 的 z-index 更大,那么它就更高 */
</style>

6b9050a912baeec05dbd06df9a776cf9.png
都为层叠上下文时,index 将决定他们的层级

关于最初 BUG 的解读

回到最初那个 bootstrap 内容框在黑底下的问题,就很方便理解了。

<div class="content">
  <div class="modal"></div> <!-- modal 内容框 -->
</div>
<div class="modal-backdrop"></div> <!-- 黑色半透明底 -->

.modal 和 .modal-backdrop 都定位了,成为了层叠上下文,而如果 .content 由于需要或误操作也创建了层叠上下文,那么 .content 和 .modal 就有了兄弟关系,谁后谁上+谁大谁上,最终造成黑底的层级高于了 .content 的层级,而 .modal 作为 .content 范围内子级也就因此被覆盖住了。

最终,要么我们把 .modal 从 .content 拿出放置于与 .modal-backdrop 同级,要么把 .content 的层级提高得比 .modal-backdrop 更大(如果 .content 还有背景色那就是另一回事了)。

所以个人认为 bootstrap 这样写是不好的,要遇上一个不懂层叠上下文的,想破头也不知道为什么。 我推荐下面的这种写法:(自创的,后来看 layui 等框架也是这样写的,看来我没做错)

<style>
.modal {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  opacity: 0;
  z-index: -1;
  overflow: hidden;
  transition: opacity .3s, z-index 0s .3s;
}
.modal-bg {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  opacity: 0;
  transition: opacity .15s;
  background: rgba(0,0,0,.8);
}
.modal.in {
  opacity: 1;
  z-index: 1;
  transition: opacity .3s, z-index 0s;
}
.modal.in .modal-bg {
  opacity: 1;
}
.modal-box {
  transform: translate3d(0,0,0);
}
</style>

<div class="modal">
  <div class="modal-bg bg"></div>  <!-- 黑底 -->
  <div class="modal-box">内容</div>
</div>

就像张鑫旭大神所说,如果你理解了层叠上下文,那么就根本不需要把 z-index 设得很大了,1-2 足矣。

非层叠上下文的覆盖关系

在张大神的 此文 中存在着这样一张图,一直让我产生着奇怪的误解。

13c331abea6817225813c15612b90339.png

后来才想通,这是非层叠上下文时的覆盖关系,但很容易让我们产生混淆。

比如 float / inline 等,和 relative 下 z-index 非 auto 一样,都是会产生覆盖,但不会创建层叠上下文。

里面的 background 和 z-index 真的实在是蛊惑人心,个人认为大可忽略不论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值