应使用transform: translateX()而非width控制侧边栏抽屉,因其触发GPU加速、不触发重排,动画更流畅;width切换会引发布局重排、耦合主内容调整且卡顿明显。

直接用 transform: translateX() 配合 transition 就能做出轻量、高性能的弹性侧边栏抽屉,不需要 JS 动画库或 CSS-in-JS。
为什么不用 width + overflow 控制显隐?
用 width: 0 / width: 280px 切换会触发重排(reflow),动画卡顿明显;且内容区域需同步调整 margin-left 或 padding-left,耦合度高、易出错。
-
transform只影响合成层,GPU 加速,60fps 更稳 - 抽屉本身保持
position: fixed或absolute,不参与文档流,不影响主内容布局 - 过渡只需控制一个属性:
transform: translateX(-280px)→translateX(0)
如何让“弹性”感更自然?
CSS 的 cubic-bezier() 是关键。默认 ease 太生硬,ease-out 收尾太急——抽屉需要“弹出去又略回弹”的物理感。
- 推荐贝塞尔曲线:
cubic-bezier(0.25, 0.46, 0.45, 0.94)(接近 iOS 弹性滚动) - 避免用
spring()函数:目前仅 Safari 支持,Chrome/Firefox 仍为实验性 - 过渡时间建议 350–450ms:短于 300ms 感觉突兀,长于 500ms 显拖沓
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
点击遮罩层关闭时,如何避免误触内容?
遮罩层(.overlay)必须覆盖整个视口,并设 z-index 高于抽屉但低于其内部可点击元素(如按钮、链接)。
立即学习“前端免费学习笔记(深入)”;
- 抽屉容器
z-index: 1000,遮罩层z-index: 999,抽屉内按钮保持默认z-index: auto - 遮罩层绑定
click关闭逻辑,但必须加pointer-events: auto(默认就是,但某些重置 CSS 会清掉) - 关键:抽屉内容区域需设
pointer-events: all,否则遮罩层会拦截所有子元素点击
移动端触摸拖拽关闭怎么做?
纯 CSS 无法实现拖拽,必须 JS 配合 touchstart/touchmove,但过渡动画仍由 CSS 承担。
- 监听
touchmove计算横向位移,动态设置style.transform = `translateX(${x}px)` - 松手时判断位移是否 > 50% 宽度:是则补全关闭,否则回弹
- 回弹动画仍走 CSS
transition,JS 只负责设最终值,不手动做帧动画 - 注意:拖拽过程中禁用
transition,否则松手瞬间会叠加两次动画
真正容易被忽略的是:抽屉打开时,body 必须加 overflow: hidden 防止页面滚动穿透;关闭后要立刻恢复,否则 iOS 上会出现滚动卡死。


















