translateX() + transition 是移动端侧边栏滑动最稳最轻量方案,因不触发重排、GPU加速、兼容性好,且避免文档流干扰。

直接用 transform: translateX() + transition 是目前移动端侧边栏滑动最稳、最轻量的方案,比 left、width 或 display 切换强得多——它不触发重排,GPU 加速默认生效,iOS 和安卓 WebView 都兼容。
为什么必须用 translateX() 而不是 left
改 left 会强制浏览器计算布局(reflow),尤其在 DOM 深、样式多的页面里,滑动一卡一卡;translateX() 属于合成层操作,只走 GPU,动画帧率更容易拉满。另一个实际影响是:用 left 隐藏时,侧边栏仍占文档流位置,主内容区可能“晃一下”;而 translateX(-100%) 完全脱离流,主内容区不受干扰。
常见错误:
-
translate(-200px)缺少轴向标识,浏览器可能解析成translateX(-200px) translateY(-200px),导致意外下移 - 写成
translateX(-200)(漏掉单位),无效 - 没给侧边栏设明确宽度(如
width: 280px),translateX(-100%)就按父容器算,滑不全
transition 必须写在哪?怎么写才不翻车
transition 必须写在侧边栏自身的基础状态上,不能只写在 .sidebar--open 里,也不能写在按钮或父容器上。否则 class 切换时,变换发生了,但过渡没被声明,就变成“瞬移”。
立即学习“前端免费学习笔记(深入)”;
推荐写法:transition: transform 0.3s ease;
别踩这些坑:
- 写成
transition: all 0.3s—— 万一后续加了color或opacity变化,会意外带出其他动画,干扰逻辑 - 把
transition放在:hover或 JS 内联样式里,失效 - 初始状态用了
display: none——transform和transition全部不生效,得先设为display: block或用visibility: hidden过渡
JS 控制显隐:class 切换是唯一靠谱方式
别在 JS 里写 el.style.transform = 'translateX(0)',这会覆盖 CSS 中定义的 transition,首次展开没动画;也容易和 rotate/scale 等其他 transform 值冲突。
正确做法是纯 class 控制:
- CSS 定义两个状态:
.sidebar--closed { transform: translateX(-100%); }和.sidebar--open { transform: translateX(0); } - JS 用
sidebarEl.classList.toggle('sidebar--open')切换 - 点蒙层关闭时用
classList.remove(),不是toggle(),避免误触二次展开 - 监听
Esc键:document.addEventListener('keydown', e => e.key === 'Escape' && sidebarEl.classList.remove('sidebar--open'))
注意:蒙层要设 position: fixed; width: 100vw; height: 100vh; touch-action: manipulation;,否则 iOS Safari 点击无响应。
移动端必须处理的三个隐藏问题
滑出后页面还能滚?那是滚动穿透。打开侧边栏时,得给 <body> 加 overflow: hidden,但 Safari 下还得补 position: fixed; top: 0; 才真正锁住。
滑动卡顿?加 will-change: transform; 到侧边栏容器(仅在打开时动态加,关掉时移除),能提前提示浏览器升层,尤其对低端安卓 WebView 有效。
焦点丢失或屏幕阅读器不可读?隐藏态别用 display: none,用 aria-hidden="true" + inert 属性(支持渐进);展开时记得 focus() 到第一个可交互元素。
最易忽略的一点:所有动画时长都得落在 0.25s–0.35s 区间——短了突兀,长了像卡死;ease 或 cubic-bezier(0.34, 1.56, 0.64, 1) 比 linear 更符合手指滑动的物理直觉。



















