HTML元素绘制层级详解

默认层级

我们在日常写页面的时候,正常情况下html元素都是按照html文档的顺序进行排布的,也就是写在后面的元素(如DIV),会显示在前一个元素(假设DIV)的下方。这种情况是最简单的,也是最好理解的。但在垂直于屏幕的Z轴方向上,浏览器是如何决定哪个元素渲染在上面,哪个元素渲染在下面的呢?先来看下面这段demo

<style>
#a{
  width: 100px;
  height: 100px;
  background: red;
}

#b{
  width: 100px;
  height: 100px;
  background: blue;
  margin-top: -50px;
  margin-left: 50px;
}
</style>

<div id='a'>I AM A DIV</div>
<div id='b'>I AM B DIV</div>

在这里插入图片描述
在上面的demo中,我们将蓝色div的margin设置为负值,让它与红色div重叠。正如我们看到的那样,蓝色div盖在了红色div的上面。也不难理解,因为在代码中蓝色div是写在红色div后面的,所以浏览器在渲染的时候,先绘制了红色div,然后再绘制蓝色div。

Z-index

那在上面的demo中,我们加入zindex属性会变成什么样呢?

<style>
#a{
  width: 100px;
  height: 100px;
  background: red;
}

#b{
  width: 100px;
  height: 100px;
  background: blue;
  margin-top: -50px;
  margin-left: 50px;
  position: relative;
  z-index: -1;
}
</style>

<div id='a'>I AM A DIV</div>
<div id='b'>I AM B DIV</div>

在这里插入图片描述
给蓝色div加上z-index属性,并将值设置为-1的时候,能看到蓝色div被渲染在了红色div的下方。这说明z-index属性对html元素的渲染层级是有影响的。但z-index值越高,渲染的层级就一定越高吗?

Transform

<style>
#a{
  width: 100px;
  height: 100px;
  background: red;
}

#b{
  width: 100px;
  height: 100px;
  background: blue;
  margin-top: -50px;
  margin-left: 50px;
  position: relative;
  z-index: -1;
}

#c{
  width: 100px;
  height: 100px;
  background: green;
  position: relative;
  z-index: 1000;
  margin-top: -50px;
  margin-left: -25px;
}
</style>

<div id='a'>I AM A DIV</div>
<div id='b'>I AM B DIV
   <div id='c'>I AM C DIV</div>
</div>

在这里插入图片描述
这里给蓝色div新增了一个子元素,该元素为绿色背景。我们将其z-index值设置为一个很大的值1000。如果按照上面z-index越大,渲染层级越高的猜测,那么绿色div应该在红色div的上层,但看的到实际情况并不是这样。这说明z-index还是被某个神秘力量限制住了。接下来就要涉及到层叠栈(stacking context) 的概念。

层叠栈(stacking context)可以简单理解为一个渲染单元,浏览器在进行渲染的时候,会独立计算这个独立单元的层级。在上面的demo中,蓝色div与绿色div为一个层叠栈,无论怎么给这两个div设置z-index值,都只会影响该栈上下文中的渲染层级。如果想要将绿色div渲染在红色div之上,那么有两种方法,一种是将绿色div的代码移到与红色div平级的位置,此时同属一个层叠栈。另一种是将红色div的z-index值设置的比蓝色div所在的层叠栈小,那么蓝色div所属的层叠栈会渲染在红色div之上。

那有没有什么奇淫技巧能在不使用上述两个方法的情况下,让红色div渲染在绿色div和蓝色div之间的呢?CSS博大精深,一定有办法。

在CSS中,还有一种能改变Z轴渲染逻辑的属性,就是transform。

<style>
#a{
  width: 100px;
  height: 100px;
  background: red;
}

#b{
  width: 100px;
  height: 100px;
  background: blue;
  margin-top: -70px;
  margin-left: 25px;
  position: relative;
  z-index: -1;
}

#c{
  width: 100px;
  height: 100px;
  background: green;
  position: relative;
  z-index: 1000;
  margin-top: 25px;
  margin-left: 25px;
  transform: translateZ(1px);
}

#container{
  transform-style: preserve-3d;
}
</style>

<div id='container'>
  <div id='a'>I AM A DIV</div>
  <div id='b'>I AM B DIV
    <div id='c'>I AM C DIV</div>
  </div>
</div>

上面demo中,在所有div前再包一层div,并设置CSS属性transform-style: preserve-3d将该层叠栈3D化。此时我们如果想要将绿色div渲染在红色div上,只需要给绿色div设置transform属性,并往Z轴正方向移动大于0px的距离即可。

总结

  • html元素的渲染层级,默认情况下是按照html内元素的书写顺序来的。

  • 通过z-index可以打破这个规则,但z-index只在同一个层叠栈(stacking context)中有效。

  • 通过transform可以打破层叠栈(stacking context)的规则,让元素可以跨栈调整渲染层级。

猜你喜欢

转载自blog.csdn.net/ForeverCjl/article/details/107708711