纯css侧边栏抽屉最轻量无障碍方案是checkbox+:checked,必须用~兄弟选择器而非+,因~匹配同级后续任意兄弟元素,+仅限紧邻兄弟;结构上input与.drawer须同父平级,否则选择器失效。

纯 CSS 实现侧边栏抽屉,checkbox + :checked 是目前最轻量、无障碍友好、且无需 JS 就能响应点击/空格键切换的方案。但它对 HTML 结构极其敏感,结构错一丁点,整个逻辑就失效。
为什么必须用 ~ 兄弟选择器,而不是 +
~ 是通用兄弟选择器,只要目标元素在 input 后面、同级、且在同一父容器下,就能命中;+ 是相邻兄弟选择器,要求目标元素必须紧挨着 input,中间不能插任何其他标签(包括注释、换行符在某些解析器里都可能破坏匹配)。
- 常见错误:把
<label></label>和<div class="drawer"> 写成父子关系,比如 <code><label><div class="drawer">...</div></label>—— 这时~和+都失效 - 正确写法:
<input id="menu-toggle" type="checkbox">和<div class="drawer"> 必须是同一父元素下的平级兄弟节点 <li>推荐 DOM 位置:把 <code><input>放在最顶层,紧接着就是<label for="menu-toggle"></label>和<div class="drawer"> <h3> <code>transform: translateX(-100%)为什么有时没完全隐藏?表面看是位移没到位,本质是计算基准出错:
-100%是按父容器宽度算的,不是按抽屉自身宽度;而抽屉若没设明确width,或父容器有padding/border,结果就会偏移。- 更稳写法:
transform: translateX(-100vw)(注意是vw,不是%),确保彻底滑出视口左边界 - 必须加:
box-sizing: border-box到抽屉容器,避免内边距干扰尺寸计算 - 调试技巧:临时加
outline: 1px solid red查看真实渲染边界,比靠眼睛猜准得多 - 别忘了给抽屉设
flex-shrink: 0(如果用 flex 布局),否则它可能被压缩变形
遮罩层(overlay)点击关闭不生效的三个硬伤
遮罩层不是装饰,它是阻止背景穿透、提供关闭入口的关键节点。但它的行为极易被忽略细节破坏。
-
.overlay必须是position: fixed,且width: 100vw; height: 100vh;—— 用100%会按父容器高度算,常导致下半截不可点 -
z-index要比抽屉低一级(比如抽屉z-index: 1000,遮罩设999),否则遮罩盖不住抽屉内容,用户仍能点到背后按钮 - 遮罩本身得是
<label for="menu-toggle"></label>,而不是普通<div> —— 否则点击不会触发 checkbox 状态翻转,自然关不了 <li>额外建议:加 <code>cursor: pointer,某些安卓 WebView 下没这个样式,点击区域响应会变迟钝
真正难的不是让菜单滑出来,而是它关掉后焦点没回到触发按钮、键盘 Tab 顺序断了、屏幕阅读器读不出“菜单已关闭”——这些纯 CSS 做不到,必须靠
aria-expanded和 JS 配合管理。如果项目要过 WCAG 2.1,checkbox方案只是起点,不是终点。 - 更稳写法:











