侧边栏抽屉必须用 transform: translateX() 配合 position: fixed 实现,因 left 或 margin-left 会触发重排导致卡顿;translateX(-100%) 失效主因是基准宽度计算错误,需设明确 width 和 fixed/absolute 定位;遮罩层需正确层级、尺寸及 label for 绑定;transition 必须写在基础样式中,且需 aria 与 JS 补全可访问性。

侧边栏抽屉效果必须用 transform: translateX() 配合 position: fixed,其他方式(如 left 或 margin-left)在 iOS Safari 和安卓 WebView 中会触发重排、掉帧甚至黄警告,不是“能用”,而是“会出问题”。
为什么不能用 left 或 margin-left 实现位移
改 left 会让浏览器每帧都重新计算布局(reflow),尤其当页面含 flex、滚动或字体渲染时,动画卡顿明显;margin-left 在部分 Android WebView 中还会导致文档流意外抖动。而 transform: translateX() 走 GPU 合成层,只重绘不重排,iOS 和 Chrome 都能稳定跑满 60fps。DevTools 里看不到报错,但 timeline 里频繁出现黄色 layout 标记,就是它在告警。
transform: translateX(-100%) 失效的常见原因
表面是没滑走,实际是位移基准算错了:-100% 按父容器宽度算,不是按侧边栏自身宽。所以必须满足三个条件:
-
.sidebar必须有明确width(如width: 280px),不能靠内容撑开或用vw单位 - 必须设
position: fixed或position: absolute,否则transform可能影响主内容流,导致页面跳动 - 初始隐藏状态写成
transform: translateX(-100%),不是-100vw——100vw包含滚动条宽度,在有竖向滚动条的页面中会导致露边
遮罩层(overlay)点击失效的硬伤
不是 JS 绑错了事件,而是 DOM 层级和尺寸没对齐。最常踩的坑有三个:
立即学习“前端免费学习笔记(深入)”;
-
.overlay必须是position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;—— 用100%会按父容器高度算,下半截点不到 -
z-index要比侧边栏低一级(如侧边栏z-index: 1000,遮罩设999),否则盖不住侧边栏内容,用户仍能点到背后按钮 - 遮罩得是
<label for="menu-toggle"></label>,而不是普通<div>—— 否则点击不会翻转checkbox状态,自然关不了抽屉
transition 写在哪才生效
动画不生效,90% 是因为 transition 没落在默认状态上。必须写在 .sidebar 的基础样式里,而不是 :checked ~ .sidebar 中:
`.sidebar {
position: fixed;
top: 0;
right: 0;
width: 280px;
height: 100vh;
transform: translateX(100%);
transition: transform 0.3s ease-out;
will-change: transform;
}
:checked ~ .sidebar {
transform: translateX(0);
}`
如果只把 transition 写在 :checked 规则里,首次打开就没有过渡,直接突变。另外,别用 transition: all,它会污染其他属性动画,且不可控。
真正难的不是让菜单滑出来,而是它关掉后焦点没回到触发按钮、Tab 键顺序断了、屏幕阅读器读不出状态变化——这些纯 CSS 做不到,得靠 aria-expanded 和 JS 补全。


















