用 transform: translateX() 而非 left 或 width 是因后者触发重排致卡顿,前者 GPU 加速、不占文档流,帧率可达 60fps;需配合 position: fixed、touch-action: pan-y、同级 overlay 及 JS 锁 body 滚动等细节保障体验。

为什么用 transform: translateX() 而不是 left 或 width
直接改 left 或 width 会触发浏览器重排(reflow),动画卡顿、跳变明显,尤其在低端安卓机上几乎不可用;transform: translateX() 走 GPU 加速,不改变文档流,动画顺滑且不影响主内容布局。这不是“看起来更酷”,而是真实滚动帧率从 30fps 拉到 60fps 的关键。
position: fixed 必须加,且不能漏掉 touch-action: pan-y
侧边栏没设 position: fixed 或 position: absolute,transform 一动就会把主内容挤偏——因为默认是 relative 定位,位移仍占文档流空间。移动端还要额外加 touch-action: pan-y 到侧边栏元素上,否则手指上下滑动时,系统无法区分是想滚动页面还是拖拽菜单,极易冲突导致手势失效或页面卡死。
- 遮罩层
.overlay必须和侧边栏同级,z-index设为比主内容高、但比侧边栏低(比如侧边栏z-index: 1000,遮罩z-index: 999) - 隐藏态写成
transform: translateX(-100%),别写死像素值如translateX(-280px),否则横屏或大屏下收不全 -
.overlay点击要能关闭菜单,所以得确保它没有pointer-events: none
纯 CSS 方案里,~ 选择器失效的常见结构错误
#menu-toggle:checked ~ .drawer 这种写法只对**同级兄弟元素**生效。很多人把 <input id="menu-toggle"> 放在 <header></header> 里,而 .drawer 放在 <main></main> 里,它们根本不在同一父容器下,CSS 就完全找不到目标。
- 正确做法:把
<input>和<div class="drawer"> 都放在 <code>最外层,平级并列 - 如果用 React/Vue 组件封装,结构必然嵌套,此时
~失效,必须换 JS 控制classList.toggle() - 关闭按钮也得用
<label for="menu-toggle"></label>,而不是再写一个 checkbox —— 同一个id关联多个 label 才能复用状态 - 别忘了在 JS 中监听
ESC键关闭菜单,这对键盘用户是刚需 - 侧边栏内部如果有长列表,需单独加
overflow-y: auto并设固定高度,否则会撑开整个视口 - 无障碍方面,展开时给侧边栏加
aria-hidden="false",遮罩层加aria-modal="true",否则屏幕阅读器会跳过整个抽屉
展开时背景还能滚动?这是默认行为,得手动锁
CSS 无法向上选择父级,所以 #menu-toggle:checked ~ body 是无效写法。背景滚动锁定必须靠 JS:展开时给 加 class="no-scroll",对应 CSS 写 body.no-scroll { overflow: hidden; }。注意不是 overflow-y: hidden,因为 iOS Safari 对这个属性支持不稳定,必须用完整的 overflow。
立即学习“前端免费学习笔记(深入)”;



















