transform: translateX() 是唯一靠谱的选择,因其走 GPU 合成层、不触发重排重绘,避免 iOS 黄警告和安卓掉帧;而 left 或 margin-left 会强制同步布局,导致动画卡顿。

必须用 transform: translateX(),不能用 left 或 margin-left —— 否则动画卡顿、iOS 报黄警告、安卓掉帧。
为什么 transform: translateX() 是唯一靠谱的选择
改 left 或 margin-left 会强制浏览器触发 layout(重排),尤其在低端安卓 WebView 和 iOS Safari 下,手指一滑就“跳帧”或“抖一下”。transform: translateX() 走 GPU 合成层,不重排、不重绘,动画顺滑。DevTools 里看到的黄色警告(“Forced synchronous layout”)基本都来自这里。
-
transform只作用于元素自身坐标系,和父容器定位无关;left却依赖position: relative等上下文,稍错就失效 - 别同时写
left: 0和transform: translateX(-100%)—— 浏览器按规范合并计算,但 Safari 有时解释为 0 位移 -
display: none或visibility: hidden会让transition直接失效,必须靠transform控制显隐
transition 必须写在默认状态,且只针对 transform
动画不生效?大概率是把 transition 写在了 .sidebar.open 里,而不是默认的 .sidebar 上。CSS 过渡只在属性值变化时触发,得让浏览器“知道你要过渡什么”。
- 正确写法:
.sidebar { transform: translateX(-100%); transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); } - 错误写法:
.sidebar.open { transition: transform 0.3s; }—— 这样打开有动画,关闭时直接突变 - 绝对不要写
transition: all 0.3s,否则color、background等无关属性也会参与过渡,拖慢性能 - 移动端可加
will-change: transform(仅在打开瞬间 set,关闭后设回auto),对旧设备有实际提升
侧边栏必须配 position: fixed 或 absolute
没设定位,translateX() 会和其他布局属性冲突,主内容区跟着“晃”,或者抽屉被父容器裁剪、位移不准。
立即学习“前端免费学习笔记(深入)”;
-
position: fixed最常用:贴视口左/右边缘,不占文档流,主内容区无需手动调整宽度或 margin -
width必须明确(如width: 280px),否则translateX(-100%)按父容器算,flex 容器里容易偏差 - 收起位移值优先用
translateX(-100vw)(不是-100%),确保彻底滑出视口左边界,不受嵌套影响 - 遮罩层
.overlay必须同级、position: fixed、width: 100vw; height: 100vh;,z-index略低于抽屉(如抽屉z-index: 1000,遮罩999)
JavaScript 切换 class 时容易漏的关键点
只写 element.classList.toggle('open') 不够,交互细节决定是否顺滑。
- 别在 click 回调里立刻 toggle class —— 加一层
requestAnimationFrame,避免样式未就绪就触发过渡 - 打开时设
document.body.style.overflowX = 'hidden'(不是overflow: hidden),否则 Safari 会跳回顶部 - 关闭后记得清空
will-change(element.style.willChange = 'auto'),长期开启可能增加内存占用 - 抽屉激活时,主内容区加
aria-hidden="true",抽屉本身设aria-hidden="false",否则屏幕阅读器仍会读背后内容
真正难的不是写出动画,而是让位移值在不同 DPR、横竖屏、缩放比例下都不越界,同时兼顾键盘操作、滚动锁定和焦点管理——这些点漏一个,用户就能感知到“差点意思”。


















