用:checked而非JS控制显隐,因其无需事件监听、兼容IE9+、空格键天然切换、无障碍支持好,且规避移动端touch事件坑;input须静态同级前置、用~选择器、transform动画、z-index分层。

为什么用 :checked 而不是 JS 控制显隐
因为不需要监听事件、不依赖运行时状态,兼容性好(IE9+),键盘空格键天然可切换,无障碍支持直接拉满。更重要的是——它规避了移动端 touch 事件绑定失败、touchend 丢失、passive: false 配置遗漏等一堆 JS 层面的坑。纯 CSS 方案在 iOS Safari 上反而更稳,尤其对低配设备或 WebView 场景。
input[type="checkbox"] 必须静态存在于 DOM 开头
不能靠 JS 动态插入,也不能藏在 display: none 容器里。否则 Safari 可能跳过渲染或不触发硬件加速,导致滑动卡顿甚至“闪现”。常见错误是把 input 放在 .sidebar 内部或末尾,结果 :checked ~ .sidebar 根本不匹配。
-
input必须和.sidebar同级,且在它前面 - 用
position: absolute; opacity: 0; pointer-events: none;隐藏它,别用display: none -
label用for="xxx"或嵌套方式绑定,确保点击区域准确
:checked ~ .sidebar 的选择器写法不能错
必须用兄弟选择器 ~,不是相邻选择器 +,也不是后代选择器 。因为 input 和 .sidebar 中间可能隔着其他元素(比如遮罩层 .backdrop),+ 会断链,~ 才能跨中间节点捕获。
- 错误:
#toggle:checked + .sidebar→ 中间插个.backdrop就失效 - 正确:
#toggle:checked ~ .sidebar→ 稳定匹配后续所有同级.sidebar - 别漏掉
z-index:侧边栏要高于主内容但低于导航栏,遮罩层.backdrop的z-index得比.sidebar略低
动画必须用 transform: translateX(),别碰 left
left 触发重排,transform 走合成层,GPU 加速。尤其在高 DPI 屏或页面缩放时,left: -280px 可能偏移不准,而 translateX(-100%) 始终相对自身宽度,更可靠。
立即学习“前端免费学习笔记(深入)”;
- 初始状态:
.sidebar { transform: translateX(-100%); transition: transform 0.3s ease-out; } - 激活状态:
#toggle:checked ~ .sidebar { transform: translateX(0); } - 千万别写
transition: all 0.3s—— 阴影、透明度变化会被拖慢,动画变糊 - 如果侧边栏有内部滚动,记得加
overflow-y: auto; height: calc(100vh - 64px);(减去 header 高度)
最麻烦的其实是遮罩层交互和 body 滚动控制——:checked 能开菜单,但关菜单时点遮罩层,得靠 JS 绑 document 监听并手动 toggle input;而禁用页面滚动也得靠类名切换(如 is-sidebar-open),不能直接改 body.style.overflow,否则动画过程中容易抖。


















