必须用transform: translateX()而非left或margin-left,因其仅触发GPU加速的合成层动画、不触发重排,避免移动端卡顿闪屏;需配合position: fixed、transition: transform 0.3s cubic-bezier、will-change: transform及body滚动锁定等完整方案。

为什么用 transform: translateX() 而不是 left 或 margin-left
直接改 left 会触发浏览器重排(reflow),尤其在移动端 Safari 上容易卡顿或闪屏;margin-left 在 flex 容器里行为不稳定,还可能被父级 overflow: hidden 截断。而 transform: translateX() 只走合成器,GPU 加速,动画顺滑,且不干扰文档流。
常见错误是写成 left: -280px → left: 0 过渡,结果动画生硬、掉帧。必须锁定 transform 单一属性做过渡。
-
transform: translateX(-100%)表示完全移出视口(比写死-280px更适配不同宽度设备) - 过渡声明必须加在抽屉容器本身,不是父元素:
transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1) - 低端安卓 WebView 或 iOS Safari 需加
will-change: transform防闪屏
position: fixed 是底线,别用 absolute 或 sticky
抽屉必须脱离文档流且始终贴左、不随页面滚动偏移。absolute 容易被父容器的 overflow: hidden 裁剪;sticky 在滚动时定位不可控;只有 fixed 能保证层级独立、尺寸稳定、遮罩层不穿模。
- 必备样式:
position: fixed; top: 0; left: 0; width: 280px; height: 100vh; - 漏掉
height: 100vh会导致滚动时抽屉只覆盖可视区,内容被截断 - 移动端必须加
touch-action: none,否则手指滑动会穿透到背后页面
点击按钮没反应?先查这三处 DOM 和绑定问题
多数失效不是动画写错,而是 JS 没绑上——尤其动态渲染或异步加载场景下。
立即学习“前端免费学习笔记(深入)”;
- JS 执行时机不对:没等 DOM 加载完就
querySelector,应包在DOMContentLoaded里,或把 script 放在</body>前 - 选择器不匹配:按钮的
data-target="#drawer"和侧边栏id="drawer"大小写/拼写不一致 - 框架环境误用原生绑定:Vue/React 中抽屉是动态挂载的,不能靠初始
document.querySelector绑定,得用事件委托或生命周期钩子
遮罩层和背景滚动穿透怎么防?光 overflow: hidden 不够
仅给 <body> 加 overflow: hidden,iOS Safari 会保留当前滚动位置,松手后突然回弹;键盘 Tab 仍能跳进隐藏区域;鼠标还能点透遮罩。
- 抽屉打开时,给
<body>同时加overflow: hidden和inert属性(现代浏览器支持),降级方案是遍历所有可聚焦元素临时设tabindex="-1" - 遮罩层
.overlay必须与抽屉同级、z-index高于主内容但低于抽屉,且监听click时严格校验event.target === overlay,避免点内部按钮也触发关闭 - 必须监听
Escape键,并在关闭后把焦点移回触发按钮,否则键盘用户会迷失
transform 样式,或没恢复 body 的原始 tabindex 和滚动状态——这些细节在多轮开关后才会暴露。



















