用 transform: translateX() 而非 left 或 margin-left,因其触发 GPU 加速合成层,避免强制同步布局与重排,保障 60fps 流畅动画;而 left/margin-left 会频繁触发 Layout,导致卡顿及 iOS 黄色警告。

为什么用 transform: translateX() 而不是 left 或 margin-left
直接改 left 或 margin-left 会触发浏览器 Layout(重排),每帧都要重新计算布局,尤其在页面含 flex 容器、动态字体或滚动时,动画卡顿明显;iOS Safari 还会在 DevTools 的 Rendering 面板里标出黄色警告,提示“强制同步布局”。transform: translateX() 走合成层(GPU 加速),只重绘不重排,主线程几乎不参与,60fps 更稳。
常见错误现象:transition 写了但动画像幻灯片一样突变、快速开关时有粘滞感、安卓低端机掉帧严重——大概率是用了 left 或没设 position: fixed。
如何确保 translateX(-100%) 真的滑出视口
translateX(-100%) 失效,不是 CSS 写错了,而是位移基准算错了:-100% 按父容器宽度算,而父容器可能是 body 或 flex .row,宽度不可控。必须满足三个硬性条件:
-
.sidebar必须有明确width(如width: 280px),不能靠内容撑开、不能用vw单位 - 必须设
position: fixed或position: absolute,否则transform可能影响主文档流,导致页面跳动 - 初始隐藏推荐用
transform: translateX(-100vw),不是-100%——100vw是视口宽度,不含滚动条,更可靠
transition 必须写在默认状态,且别漏 visibility
动画不生效,90% 是因为 transition 没落在基础样式上。它必须写在 .sidebar 的默认声明里,而不是只写在 :checked ~ .sidebar 或 .sidebar-open 中。
立即学习“前端免费学习笔记(深入)”;
另外,仅靠 transform 过渡不够:关闭时若直接设 visibility: hidden,会瞬间消失,导致点击穿透(点到背后按钮)。正确做法是:
- 给
.sidebar加transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) - 给遮罩层
.overlay加transition: opacity 0.3s, visibility 0.3s(visibility必须显式声明时长) - 不要用
display: none控制显隐——它会让整个transition失效
移动端防滚动穿透和手势冲突
抽屉打开时用户滚动页面,背景动、抽屉不动,视觉割裂;更糟的是 iOS Safari 会把 body 滚动位置重置到顶部,键盘弹起后也恢复不了。
不能只靠 body { overflow: hidden }。稳妥方案是:
- 打开抽屉时,记录
document.documentElement.scrollTop - 给
body加position: fixed; top: -scrollTop; width: 100% - 关闭时还原
body样式,并用setTimeout(() => window.scrollTo(0, scrollTop), 0)延迟恢复滚动位置 - 侧边栏容器加
touch-action: pan-y,避免横向滑动手势被系统误判为页面滚动
真正难的不是写出滑动,而是让滑动在各种机型、各种交互路径下都“不抢焦点、不吞点击、不丢滚动位置”——这些细节一漏,用户就会觉得“卡”或者“关不掉”。


















