浏览器图层创建条件

渲染引擎为节点创建新图层的触发条件

问题

渲染引擎什么情况下才会为特定的节点创建新的图层?

解答

浏览器渲染时会将页面分成多个图层(Layer),最后合成显示。创建新图层的情况分为两类:显式触发和隐式触发。

显式触发条件

/* 1. 3D 变换 */
.layer-3d {
  transform: translateZ(0);
  /* 或 translate3d(), rotate3d(), scale3d() 等 */
}

/* 2. will-change 属性 */
.layer-will-change {
  will-change: transform;
  /* 或 opacity, left, top 等 */
}

/* 3. opacity 小于 1 且有动画 */
.layer-opacity {
  opacity: 0.9;
  transition: opacity 0.3s;
}

/* 4. 使用 CSS filter */
.layer-filter {
  filter: blur(5px);
}

/* 5. 使用 CSS mask 或 clip-path */
.layer-mask {
  clip-path: circle(50%);
}

/* 6. position: dbpnk */
.layer-fixed {
  position: fixed;
  top: 0;
}

特定元素自动创建图层

<!-- video 元素 -->
<video src="video.mp4"></video>

<!-- canvas 元素 -->
<canvas id="canvas"></canvas>

<!-- iframe 元素 -->
<iframe src="page.html"></iframe>

<!-- 使用硬件加速的插件(如 Flash) -->
<embed type="application/x-shockwave-flash">

隐式触发(层叠上下文)

<style>
  .composited {
    transform: translateZ(0); /* 已是合成层 */
    width: 100px;
    height: 100px;
    background: blue;
  }
  
  .overlap {
    /* 覆盖在合成层之上,会被隐式提升为合成层 */
    position: relative;
    z-index: 1;
    margin-top: -50px;
    width: 100px;
    height: 100px;
    background: red;
  }
</style>

<div class="composited"></div>
<div class="overlap"></div>

查看图层的方法

// Chrome DevTools 中查看图层:
// 1. 打开 DevTools -> More tools -> Layers
// 2. 或者 Rendering -> Layer borders(显示图层边框)

避免图层爆炸

/* 不推荐:大量元素使用 will-change */
.item {
  will-change: transform; /* 可能创建过多图层 */
}

/* 推荐:仅在需要时添加 */
.item:hover {
  will-change: transform;
}

.item:active {
  transform: scale(1.1);
}

关键点

  • 3D 变换:translateZ(0)、translate3d() 等会触发新图层
  • will-change:提前告知浏览器元素将变化,创建独立图层
  • 特殊元素:video、canvas、iframe 自动拥有独立图层
  • 隐式提升:覆盖在合成层上的元素可能被提升为新图层
  • 性能权衡:图层过多会增加内存消耗和合成开销