乐趣区

关于前端:CSS入门到进阶-用transform后zindex失效了总结transform的注意事项

我是 HullQin,公众号 线下团聚游戏 的作者(欢送关注公众号,发送加微信,交个敌人),转发本文前需取得作者 HullQin 受权。我独立开发了《联机桌游合集》,是个网页,能够很不便的跟敌人联机玩斗地主、五子棋等游戏,不免费没广告。还开发了《Dice Crush》加入 Game Jam 2022。喜爱能够关注我 HullQin 噢~我有空了会分享做游戏的相干技术。

背景

这篇文章,我讲了如何实现自适应屏幕宽度的 canvas:《如何实现响应式 canvas?放弃 canvas 比例?教你让 canvas 自适应屏幕宽度!》,其中 canvas 的缩放依赖了 transform 这个 CSS 属性。

transform是指针对元素做一些 2D/3D 转换,本文解说相干注意事项。

它在 dom 元素占据的地位,是变换前的形态和大小

transform的很多变换,都会批改 dom 元素的形态。

咱们晓得,transform只能作用于盒子模型的元素上,通常咱们接触的都是盒子模型,例如display: block

而这些元素,初始都是矩形,并且很正(是横平竖直的矩形)。

变换后,可能通过了旋转、拉伸,可能就变成了歪歪的平行四边形。

而 transform 变换后,该元素在 dom 中所占据的地位,是不会变换的!

也就是说,如果被 transform 变换的元素 A,如果它前面有其它元素 B,那么不论你咋变换 A,B 的地位是不会受影响的。这样 DOM 渲染效率就会高。

想想,为什么这么设计?

构想这样的情景:transform 能够联合动画应用。如果你放了一个始终在旋转的矩形,那么它在 y 轴撑开的高度每时每刻都在扭转,让它前面所有元素随着动画扭转 y 坐标的话,就须要批改太屡次了,重大影响性能。因而,transform 变换后,元素在 dom 中所占据的地位,是不会变换的。

参考例子:

码上掘金

它的展现成果,会笼罩在其它元素上,无论其它元素 z -index 多大

参考例子:

码上掘金

这是因为 层叠上下文 (Stacking Context),当你给一个元素设定了 transform 属性,它就是“出人头地”,会笼罩在其它没有 transform 元素的下面,无论其它元素的 z-index 有多大。

文档中的层叠上下文由满足以下任意一个条件的元素造成:

  • 文档根元素(<html>);
  • position 值为 absolute(相对定位)或  relative(绝对定位)且 z-index 值不为 auto 的元素;
  • position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有挪动设施上的浏览器,但老的桌面浏览器不反对);
  • flex (flex) 容器的子元素,且 z-index 值不为 auto
  • grid (grid) 容器的子元素,且 z-index 值不为 auto
  • opacity 属性值小于 1 的元素(参见 the specification for opacity);
  • mix-blend-mode 属性值不为 normal 的元素;
  • 以下任意属性值不为 none 的元素:

    • transform
    • filter
    • backdrop-filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • isolation 属性值为 isolate 的元素;
  • will-change 值设定了任一属性而该属性在 non-initial 值时会创立层叠上下文的元素(参考这篇文章);
  • contain 属性值为 layoutpaint 或蕴含它们其中之一的合成值(比方 contain: strictcontain: content)的元素。

放缩、旋转等波及「中心点」的变换,默认选元素正核心为「中心点」,可通过 transform-origin 批改

例如scale,默认是以核心来放大放大的。也就是说,放缩前后:中心点地位不变。

通常针对 scale,咱们会习惯设置transform-origintop或者top left,别离是以顶部两头为核心、以左上角为核心。

易踩坑的点: 0.5px 分割线

如果你心愿实现 0.5px 的分割线,并且这个分割线是用 div 实现的。你可能这么写:

<div class="divider"></div>
.divider {
  height: 1px;
  transform: scaleY(0.5);
  background-color: gray;
}

但这样不对,因为它只是 UI 展现了 0.5px 高度,其实它仍然是占据了 1px 的高度(参考第一点注意事项)。分割线跟其下方的其它元素的间隔会有 0.25px 的误差(参考第三点注意事项)。

所以你最好这么写 0.5px 的分割线:

.divider {
  height: 1px;
  transform: scaleY(0.5);
  transform-origin: top;
  margin-bottom: -0.5px;
  background-color: gray;
}

凡是你是个谋求极致的人,或者你的设计师是个谋求极致的人,都容易发现这 0.5px 的误差。不要被坑啦!如果你有播种,麻烦点个收费的赞噢,感激!

写在最初

我是 HullQin,公众号 线下团聚游戏 的作者(欢送关注公众号,发送加微信,交个敌人),转发本文前需取得作者 HullQin 受权。我独立开发了《联机桌游合集》,是个网页,能够很不便的跟敌人联机玩斗地主、五子棋等游戏,不免费没广告。还开发了《Dice Crush》加入 Game Jam 2022。喜爱能够关注我 HullQin 噢~我有空了会分享做游戏的相干技术。

退出移动版