toFrankie / blog

种一棵树,最好的时间是十年前。其次,是现在。
22 stars 1 forks source link

overflow 使得 transform-style 失效了 #176

Open toFrankie opened 1 year ago

toFrankie commented 1 year ago

配图源自 Freepik

这周做了一个需求,出现了 Bug,经排查后发现:

同一元素同时设置 overflow: hiddentransform-style: preserve-3d 样式,会使得后者失去 3D 效果,也就是相当于 transform-style: flat

下面用示例验证一下:

<div class="container">
  <div class="rect red"></div>
  <div class="rect green"></div>
</div>

.constainer 区域设置了 transform-style: preserve-3d.red 区域设置了 transform: translate3d(20px, 20px, 10px).green 区域设置了 transform: translate3d(0, 0, 5px)

👇

.container {
  margin: 0 auto;
  border-radius: 10px;
  padding: 10px;
  width: 200px;
  height: 200px;
  background: #f8f8f8;
  transform-style: preserve-3d;
}

.rect {
  box-sizing: border-box;
  border: 2px solid #000;
  border-radius: 4px;
  width: 100px;
  height: 100px;
}

.red {
  background: #f00;
  /* translateZ 为 10px */
  transform: translate3d(20px, 20px, 10px);
}

.green {
  background: #0f0;
  /* translateZ 为 5px */
  transform: translate3d(0, 0, 5px);
}

由于红色区域与绿色区域置于 3D 空间中,其中红色在 Z 轴更上面,因此实际表现如下,与预期一致。 👇

一旦,将 overflow: hidden 应用于 .container

.container {
  margin: 0 auto;
  border-radius: 10px;
  padding: 10px;
  width: 200px;
  height: 200px;
  background: #f8f8f8;
  transform-style: preserve-3d;
  /* 新增 */
  overflow: hidden
}

那么结果就... 👇

在不同设备实际表现还不一样,应该是渲染内核实现不一致导致的。FireFox 浏览器同左边表现一样。 其中左边为「非预期效果」,右边为「预期效果」。

示例可看:👉 CodePen

我们分析一下左边的原因:

我们知道,使用 transform 会使得元素创建一个「层叠上下文」,也就是说 .red.green 是两个不同的层叠上下文。由于这里并没有使用 z-index 来控制元素的「层叠顺序」,加上 overflow: hidden 使得 transform-style: preserve-3d 失去了 3D 空间效果,因此无法通过 transform: translateZ() 的大小来控制层叠顺序。因此在文档流中遵循「后者居上」的原则,使得 .green 处于 .red 的上方(即左边的表现)。

因此,可得出结论:

在「非 Webkit 内核」中,同一元素同时设置 overflow: hiddentransform-style: preserve-3d 样式,会使得后者失去 3D 效果,也就是相当于 transform-style: flat

注意,以上结论表述为「非 Webkit 内核」可能不严谨。原因是:以上 Chrome 为 Mac 平台的截图,查看了其 UA 是 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 标注的是 Webkit 内核,难道实际是 Google 的 Blink 内核(虽说 Blink 师出 Webkit)?如果是的话,表述就没问题了。

有时候,犯错了印象才会更加深刻...