必须用 transform: translatex() 而不是 left 或 margin-left,因其走 gpu 合成层、只重绘不重排,可稳住 60fps;left/margin-left 触发重排,易卡顿、闪动、降级警告。

为什么必须用 transform: translateX() 而不是 left 或 margin-left
因为 left 和 margin-left 触发重排(reflow),动画一跑就卡,尤其在低端安卓机或 iOS Safari 上会掉帧、闪动、弹黄色“强制降级”警告;transform: translateX() 走 GPU 合成层,只重绘不重排,是唯一能稳住 60fps 的方案。
常见错误现象包括:left: -100% 在 iOS 收起时闪一下才消失;点击后抽屉“顿半拍”才动;快速连点两次,位移错乱。这些基本都是定位属性混用或未触发合成层导致的。
transform: translateX(-100%) 的宽度基准到底是啥?
它基于元素自身的 width,不是父容器,也不是视口。所以必须确保抽屉容器有明确宽度声明,比如 width: 280px 或 max-width: 280px。否则 -100% 行为不可控——缩放页面、横竖屏切换时可能偏移不准。
如果宽度固定且无需适配,直接写 translateX(-280px) 更稳妥,避免视口缩放干扰;但若需响应式(如 width: 70vw),就只能依赖 -100%,并确保父级无 overflow: hidden 等破坏合成层的样式。
- 别同时写
left和transform:浏览器合并计算行为不可控,Safari 可能直接忽略translateX() -
display: none或visibility: hidden不能用于初始隐藏——transition会失效 - 初始隐藏必须靠
transform: translateX(-100%)写死在默认样式里
如何让 translateX() 真正走 GPU 加速?
仅写 transform + transition 不够,很多真机上仍抖、有白边、iOS 被截断,是因为没触发独立合成层。必须三件套齐上:
-
position: fixed(或absolute):脱离文档流,避免挤压主内容;设top: 0; left: 0; width: 280px; height: 100vh -
backface-visibility: hidden:iOS Safari 必加,否则拉出一半常出现白边或闪烁 -
will-change: transform:仅在打开/关闭前瞬间通过 JS 设置(el.style.willChange = 'transform'),动画结束立刻设回'auto',长期开着吃内存
兼容性兜底可加 transform: translateZ(0),比 will-change 更老浏览器友好,但别和 opacity 动画混用——这会让合成层失效。
遮罩层与滚动锁定怎么配才不翻车?
遮罩层不是摆设,它决定点击是否可靠、背景是否乱滚。“点不关”“关了还能滑”基本都出在这儿。
.overlay 必须:position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;(别用 100%,某些安卓浏览器算的是父容器高度);z-index 设为 10,侧边栏设为 11,主内容区为 1 —— 否则 iOS 上 touchstart 可能穿透到下层。
滚动锁定不能只靠 body { overflow: hidden },iOS Safari 会把滚动位置重置到顶部。正确做法是:body.no-scroll { overflow: hidden; height: 100vh; overscroll-behavior: contain; },JS 打开时立即加,关闭时**立刻移除**(别等 transitionend),否则键盘弹起后无法恢复滚动位置。
点击穿透防不住?动画结束后,除了 translateX(-100%),还得显式设 visibility: hidden + pointer-events: none,必要时加 display: none(用 setTimeout 兜底,比如 350ms 后)——快速连点时 transitionend 容易丢失。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











