移动端侧边抽屉必须用 transform: translatex() 而非 left,因后者触发 layout+paint,前者仅走合成器线程、gpu加速;需配合 100dvh、body 溢出隐藏及遮罩层正确事件处理。

抽屉菜单用 transform 还是 left?选错就卡顿
移动端侧边抽屉必须用 transform: translateX(),别碰 left。因为 left 触发 layout + paint,而 transform 只走合成器线程,GPU 加速,滚动/动画不掉帧。iOS Safari 尤其敏感,left 在 60fps 下直接掉到 30fps 以下。
实操建议:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 抽屉容器设
position: fixed或absolute,宽高撑满视口,top: 0; left: 0; - 默认状态写
transform: translateX(-100%);(完全隐藏),不要用display: none或visibility: hidden—— 它们会破坏 transform 动画的连续性 - 弹出时只改
transform: translateX(0);,配合transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
overflow: hidden 放 body 还是抽屉父容器?位置错了会透出滚动条
必须加在 body 上,且要在抽屉打开时动态添加 class。如果只加在抽屉 wrapper 上,body 仍可滚动,页面内容会“被拖着走”,尤其在 iOS 上触发 bounce 效果,视觉上像整个页面在晃。
常见错误现象:抽屉弹出后,手指上下滑动,背景内容跟着动,松手还回弹。
实操建议:
- 定义
.no-scroll { overflow: hidden; height: 100vh; },JS 打开抽屉时给document.body加这个 class - 关闭抽屉后立即移除,别等 transition 结束再移 —— 否则关闭瞬间用户还能滑两下
- 别忘了处理 iOS 的
touchmove阻止:加body.no-scroll { overscroll-behavior: contain; }
点击遮罩层关闭抽屉时,如何避免误触背景元素?
遮罩层(overlay)必须覆盖整个视口,z-index 高于抽屉内容但低于抽屉本身,且要阻止事件穿透。否则点 overlay 关抽屉的同时,可能顺手触发了背后按钮的 click。
实操建议:
- 遮罩层用
position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;,别用100%—— 它在某些安卓浏览器里算的是父容器高度,不是视口 - 加
pointer-events: auto;(默认就是),抽屉内容区域设pointer-events: auto;,确保内部按钮可点;遮罩层本身不设pointer-events: none - 监听遮罩层的
click,而不是touchend—— 后者在快速点击时可能漏触发
为什么 iPhone X+ 上抽屉底部总有一条白边?
是安全区域没适配。iPhone X 及后续机型底部有 home indicator 区域,height: 100vh 会超出可视区域,导致抽屉底部留空或滚动条错位。
实操建议:
- 抽屉容器用
height: 100dvh;(dynamic viewport height),比100vh更准,能自动扣除安全区域 - 后备方案加
@supports (height: 100dvh) {},不支持的浏览器 fallback 到100vh+padding-bottom: env(safe-area-inset-bottom); - 遮罩层也要同步用
100dvh,否则盖不住底部
抽屉动画的丝滑感,90% 来自 transform + dvh + body 锁定这三件事;剩下 10% 是 timing-function 和 touch 响应细节。别在动画里塞 box-shadow 或 filter,它们会强制重绘,一加就卡。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










