必须用 translateX 而非 left:因 transform 触发 GPU 合成、不触发重排,而 left 引发 layout 计算致卡顿;初始隐藏用 translateX(-100%) 适配宽度;transition 仅限 transform;遮罩 pointer-events 需动态控制;touch 拖拽需 preventDefault 和 passive: false。

直接用 transform: translateX(),别碰 left 或 margin-left——前者触发重排、卡顿明显,iOS Safari 里还会报黄色降级警告;后者在移动端容易带出横向滚动条,且动画帧率不稳。
为什么必须用 translateX 而不是 left
浏览器对 transform 属性有成熟的 GPU 合成层支持,translateX() 不改变文档流、不触发 layout,动画走合成线程,滑动顺滑。而 left 改变的是布局属性,每次重绘都要重新计算位置+尺寸+边距,尤其在低端安卓机或 iOS WebKit 下掉帧严重。
- 初始隐藏必须写
transform: translateX(-100%),不是-280px——百分比能适配不同宽度的抽屉,避免因 padding 或 box-sizing 导致偏移 - 别在
:root或通用选择器上写transition: all,会污染其他元素动画 - 过渡只声明
transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1),别加opacity或width在同一行,否则关闭时可能错位
遮罩层 pointer-events 的时机陷阱
遮罩层(overlay)的 pointer-events 必须动态控制,不能静态设 none 或一直 auto。常见错误是:抽屉打开后点遮罩没反应,或者连点多次触发重复关闭。
- 抽屉开始展开时,遮罩立刻设
pointer-events: auto - 抽屉关闭动画进行中,仍保持
pointer-events: auto(否则中途点不了) - 仅在
transitionend事件触发后,才设pointer-events: none - 别靠
opacity: 0判断是否隐藏——它不影响点击穿透,pointer-events才是开关
移动端 touch 拖拽关闭必须加 preventDefault
iOS Safari 默认把横向 touchmove 当作页面滚动处理,不加干预拖拽就失效。光绑 touchmove 不够,关键在事件监听选项和起点拦截。
立即学习“前端免费学习笔记(深入)”;
-
touchstart时必须调用event.preventDefault() -
touchmove监听器要传{ passive: false },否则浏览器忽略preventDefault - 位移计算用
event.touches[0].clientX,不用pageX(缩放时不准) - 松手后判断拖动距离是否超过阈值(如 50px),决定是回弹还是彻底关闭
真正难的不是写几行 transform,而是状态切换和 DOM 更新之间的微小时间差——比如 React 里 useState 更新后立即读 getBoundingClientRect(),拿到的可能是旧尺寸;Vue 里 v-if 切换后立刻查宽高,得等 $nextTick。这些细节不处理,动画起始位置就飘。


















