必须用 transform: translatex() 实现侧边栏抽屉,因其走 gpu 合成层、不触发布局、保障 60fps 流畅;禁用 left/margin-left 防卡顿闪动,需配合 fixed/absolute 定位、translatex(-100%) 初始隐藏、will-change 和 backface-visibility 触发独立合成层,并严格管控遮罩层与滚动锁定。

必须用 transform: translateX(),别碰 left 或 margin-left
移动端抽屉滑出卡顿、闪动、iOS 上“跳一下才展开”,90% 都是用了 left 或 margin-left。这两个属性改的是布局盒模型,每次动画都要重排(reflow),低端安卓机掉帧到 30fps 是常态;Safari 甚至会弹黄色警告说“强制降级”。transform: translateX() 走 GPU 合成层,只重绘不重排,是唯一能稳住 60fps 的方案。
常见错误现象:left: -100% 在 iOS 上收起时偶尔闪一下才消失;点击后抽屉“顿半拍”才动;快速连点两次,位移错乱。
-
translateX(-100%)是相对自身宽度的位移,适配不同设备更稳妥;但如果侧边栏宽度固定(如width: 280px),直接写translateX(-280px)更精准,避免视口缩放导致偏移不准 - 千万别同时写
left和transform:浏览器合并计算行为不可控,Safari 可能直接忽略translateX() - 初始隐藏不能靠
display: none或visibility: hidden——transition 会失效,必须用transform: translateX(-100%)写死在样式里
position: fixed + will-change: transform + backface-visibility: hidden 缺一不可
只写 transform 和 transition 还是会抖、有白边、iOS 上被截断,是因为没触发独立合成层。浏览器默认把元素画在主渲染层,动画时仍可能牵扯 layout 或 paint。
必须三件套齐上:
-
position: fixed(或absolute):脱离文档流,避免挤压主内容;设top: 0; left: 0; width: 280px; height: 100vh撑满视口 -
will-change: transform:仅在打开/关闭前瞬间加(JS 中element.style.willChange = 'transform'),动画结束立刻设回'auto',长期开着会吃内存 -
backface-visibility: hidden:iOS Safari 必加,否则抽屉拉出一半常出现白边或闪烁
示例关键声明:
.drawer {
position: fixed;
top: 0;
left: 0;
width: 280px;
height: 100vh;
transform: translateX(-100%);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
backface-visibility: hidden;
will-change: transform;
z-index: 1000;
}
.drawer.open { transform: translateX(0); }
遮罩层和滚动锁定必须手动管,不能靠 CSS 自动
“点不关”“关了还能滑”“背景跟着动”,问题几乎全出在遮罩层和 body 滚动控制上。遮罩不是视觉装饰,是交互安全线。
- 遮罩层
.overlay必须position: fixed,宽高用100vw/100vh(别用100%,某些安卓浏览器算的是父容器高度) - 层级顺序要死守:
z-index主内容区为 1,遮罩层为 10,侧边栏为 11;否则 iOS 上touchstart可能穿透到下层 - 滚动锁定必须加在
body上:document.body.classList.add('no-scroll'),对应 CSS 是.no-scroll { overflow: hidden; height: 100vh; overscroll-behavior: contain; };关闭时立刻移除,别等 transition 结束——延迟会导致松手后页面“弹一下” - 遮罩层关闭事件用
click,不是touchend;并在回调里加event.stopPropagation(),防止点到侧边栏内部也触发关闭
响应式断点里必须显式关掉 transition
大屏下侧边栏常驻,但很多人只改 width 和 transform,忘了关 transition。结果窗口缩放时,侧边栏自己“抽风滑动”,尤其在 Chrome 桌面端 resize 过程中高频触发。
- 在
@media (min-width: 768px)里必须写:transition: none或transition-duration: 0s - 优先用
min-width断点,max-width在移动端可能因地址栏缩放误判(比如 Safari 地址栏收起时视口高度突变) - 划入期间给
body加overflow-x: hidden,防横向滚动条闪现;iOS Safari 不稳定时补一句position: fixed; width: 100vw
真正难的不是写出来,是每处都得对齐:transform 的合成层、遮罩的点击范围、触摸事件的边界判定,三者稍有脱节,体验就断了。iOS Safari 对 transform + fixed 的渲染仍有偶发 bug,will-change 不是可选项,是保底提示。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











