必须用 transform: translateX() 而非 left 或 margin-left,因其走 GPU 加速、不触发重排,避免低端设备掉帧;iOS WebKit 会对非 transform/opacity 动画报黄警告。

为什么必须用 transform: translateX() 而不是 left 或 margin-left
直接改 left 或 margin-left 会触发浏览器 Layout(重排),尤其在低端安卓机或 iOS Safari 中,动画掉帧明显;transform: translateX() 属于合成层操作,走 GPU 加速,不打断渲染流水线,滑动顺滑。iOS WebKit 还会对非 transform/opacity 的动画属性打黄色警告(DevTools 可见)。
常见错误现象:
– 抽屉“瞬移”出现/消失,无过渡
– 滑动过程中主内容区轻微晃动
– 点击按钮后延迟半秒才开始动
- 侧边栏容器必须设
position: fixed或position: absolute,否则transform对 static 元素无效 - 初始隐藏写成
transform: translateX(-100%),不是-280px——百分比基准是元素自身宽度,需确保抽屉有明确width(如width: 280px)或max-width - 别用
display: none切换状态,它会让transition完全失效;改用visibility: hidden+opacity: 0+pointer-events: none做收尾控制
transition 必须写在基础状态上,不能只靠 class 切换
很多人把 transition: transform 0.3s 写在 .drawer--open 类里,结果关闭时没动画——因为关闭时该 class 被移除,样式回退到无 transition 的默认状态。
正确写法是:transition 声明始终挂在抽屉容器的基础选择器上,例如:
立即学习“前端免费学习笔记(深入)”;
.drawer {
transform: translateX(-100%);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
这样无论加还是删 .drawer--open,只要 transform 值变化,过渡就生效。
- 避免写
transition: all 0.3s——后续加color或background变化会意外触发动画 - 不要把
transition放在:hover、:checked伪类里,或 JS 内联样式中,容易失效 - 遮罩层(
.drawer-overlay)要单独配transition: opacity 0.3s, visibility 0.3s;visibility必须显式声明时长,否则切换瞬间消失会导致点击穿透
贝塞尔曲线选 cubic-bezier(0.34, 1.56, 0.64, 1) 还是 ease-out
Material Design 官方 Drawer 用的就是 cubic-bezier(0.34, 1.56, 0.64, 1),它模拟物理滑动的“慢进快出+轻微过冲”,比默认 ease 更有抽屉感,连续开关也不粘滞。
但这个值在 iOS 12 及更早 Safari 中可能解析异常,表现为动画卡死或跳变。
- 如需兼容旧版 iOS,降级为
ease-out,并补上will-change: transform提示浏览器优化帧率 - 别在
:root或通用选择器上写全局transition,容易污染其他组件动画 - 移动端建议加
backface-visibility: hidden和will-change: transform(可选),对复杂 DOM 或长列表有实际帧率提升
右侧抽屉和滚动锁定的两个关键细节
右侧抽屉只需把初始值换成 transform: translateX(100%),展开时切为 translateX(0),其余逻辑完全一致。但有两个常被忽略的点:
- body 滚动锁定不能只靠
overflow: hidden——iOS Safari 会重置滚动位置到顶部;正确做法是记录scrollTop,然后设body.drawer-open { position: fixed; top: -scrollTop; width: 100%; },关闭后再用setTimeout(() => window.scrollTo(0, scrollTop), 0)恢复 - 遮罩层必须与抽屉同级、
z-index略低(如抽屉z-index: 1001,遮罩z-index: 1000),且宽高为100vw/100vh;否则点击区域缺失,或误触背景链接
真正难的不是让抽屉动起来,而是让 transform 的层级、遮罩的点击范围、滚动锁定的时机三者严丝合缝——任一环节松动,用户就会感知到“卡”“闪”“关不掉”。


















