必须用transform:translateX()配合position:fixed,因left/margin-left会触发重排导致掉帧、白屏;translateX走GPU合成层,60fps稳定;需设明确width、transition写在默认状态、遮罩与侧边栏同级且全屏fixed定位。

必须用 transform: translateX() 配合 position: fixed,否则在 iOS Safari 和多数安卓 WebView 中会掉帧、白屏、甚至卡死——这不是“效果差异”,是能否正常工作的分界线。
为什么不能用 left 或 margin-left
改 left 会强制浏览器每帧重算布局树(reflow),尤其当页面含 flex、滚动或字体加载时,Timeline 里满屏黄色 layout 标记;margin-left 在部分 Android WebView 中还会导致主内容意外抖动。而 transform: translateX() 走 GPU 合成层,只重绘不重排,60fps 稳定可测。
-
translateX(-100%)按自身宽度计算位移,但前提是侧边栏有明确width(如width: 280px),不能靠内容撑开或用vw单位 - 若用
translateX(-100vw),需注意竖向滚动条存在时,100vw包含滚动条宽度,可能露边 - 绝对/固定定位不是“为了好看”,而是防止
transform影响文档流——没设position: fixed的元素做translateX,主内容会跳动
transition 必须写在默认状态上,且不能写 all
动画不生效,90% 是因为 transition 只写在 .sidebar.open 里,首次展开无过渡;更糟的是写 transition: all 0.3s,一旦意外修改 z-index 或 visibility,动画就中断或闪屏。
- 正确写法:
.sidebar { transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); } - 遮罩层(
.overlay)要单独控制:transition: opacity 0.3s, visibility 0.3s;——visibility不显式声明时长,关闭瞬间消失,点击会穿透 - 别在
:root或通配符里加全局transition,按钮、卡片等其他组件动效会被污染
遮罩层点击失效的三个硬性条件
点遮罩关不了抽屉?不是 JS 绑错了,是 DOM 层级和尺寸根本没对齐。
立即学习“前端免费学习笔记(深入)”;
-
.overlay必须是position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;—— 用100%是错的,它相对父容器,不是视口 -
z-index要比侧边栏低一级(如侧边栏z-index: 1000,遮罩设999),但高于主内容;同时确保没被position: relative父容器截断层级 - 遮罩得是
<label for="menu-toggle"></label>,而不是普通<div>—— 否则点击不会翻转checkbox状态,自然关不了抽屉
移动端滚动穿透和 body 锁死失效怎么办
iOS Safari 对 body { overflow: hidden } 常常忽略,光靠这个锁不住背景滚动。
- 抽屉打开时,给
body加 class(如drawer-open),CSS 写成:.drawer-open { position: fixed; width: 100%; height: 100%; overflow: hidden; } - 侧边栏容器自身必须设
overflow-y: auto和明确高度(如height: 100vh),否则内容一多就撑出屏幕 - 如果侧边栏用了 flex 布局,内部滚动区域要加
min-height: 0,防止 flex 项撑高容器导致滚动失效
最易被忽略的是:纯 CSS 方案中 input[type="checkbox"] 和抽屉容器必须是同级兄弟节点,且用 ~(通用兄弟选择器)连接;中间插一个空格、注释或任意标签,整个逻辑就失效。


















