纯 CSS 侧边栏抽屉必须用 transform: translateX() 配合 position: fixed/absolute 实现,避免 left 或 margin-left 引发重排与兼容问题;隐藏需用 -100vw 而非 -100%;遮罩须为同级 <label> 且占满视口。

纯 CSS 实现侧边栏抽屉,transform: translateX() 是唯一靠谱的位移方式——它不触发重排、走 GPU 加速、iOS Safari 无警告;但必须搭配 position: fixed 或 position: absolute,否则位移会干扰文档流,主内容跳动。
为什么不能用 left 或 margin-left
改 left 或 margin-left 会强制浏览器每帧计算布局(reflow),低端安卓机掉帧明显;iOS Safari 还会在 DevTools 里报黄色降级警告。而 transform: translateX() 属于合成层操作,动画顺滑且兼容性好。
- 错误写法:
transition: left 0.3s→ 滚动时抽屉“跳一下”或卡顿 - 别混用:
left: 0和transform: translateX(-100%)同时存在,部分 Safari 会忽略位移 -
margin-left在 flex 容器里行为不可控,尤其当父容器有justify-content时
抽屉容器必须设 fixed/absolute 定位
不加定位,transform 仍按文档流渲染,抽屉一滑,<main></main> 内容跟着左移或抖动。只有脱离文档流,才能真正“抽”出来而不影响主区域。
- 推荐
position: fixed:宽高设为width: 280px; height: 100vh;,top/left 固定锚点 - 若用
position: absolute,父容器必须position: relative,且高度要撑满(如min-height: 100vh) - 别忘了加
box-sizing: border-box,避免 padding/border 导致宽度溢出
隐藏状态必须用 translateX(-100vw),不是 -100%
-100% 是按父容器宽度算的,而父容器可能是 body、flex 容器或带 padding 的 wrapper,结果经常偏移、没完全藏住。用 -100vw 才能确保彻底滑出视口左边界。
立即学习“前端免费学习笔记(深入)”;
- 正确:
.drawer { transform: translateX(-100vw); } - 错误:
.drawer { transform: translateX(-100%); }(尤其在 flex 布局中失效概率高) - 调试技巧:临时加
outline: 1px solid red查看真实渲染框,比肉眼判断准得多
遮罩层必须是 label 且占满视口
遮罩不是装饰,它是点击关闭的关键入口,也是阻止背景穿透的屏障。普通 <div class="overlay"></div> 点击无效——它不会触发 checkbox 状态翻转。
- 结构上必须是
<label for="menu-toggle"></label>,且与<input id="menu-toggle">同级 - CSS 中设
position: fixed; width: 100vw; height: 100vh; z-index: 999;(抽屉 z-index 至少 1000) - 加
cursor: pointer,某些安卓 WebView 下没这个样式,点击响应会变迟钝
真正容易被忽略的是:遮罩和抽屉的 DOM 顺序必须严格同级,中间不能插任何元素(包括注释和换行符),否则 ~ 兄弟选择器直接失效;还有 will-change: transform 必须只在动画期间设置,长期开启会吃内存。这些细节错一个,抽屉就动不了。


















