抽屉容器必须用 包裹,因其是唯一被所有主流屏幕阅读器识别为导航区域的语义元素;transform: translateX(-100%) 比 left: -300px 更可靠;遮罩层须与抽屉同级且独立定位;移动端滚动锁定应使用 position: fixed 配合动态 top 值,而非仅 overflow: hidden。

抽屉容器必须用 <nav></nav> 包裹,不能只用 <div>
<p>浏览器对语义化结构有隐式行为:没包在 <code><nav></nav> 里的侧边栏,Safari iOS 会跳过焦点、忽略 aria-expanded 切换,甚至不触发 transform 动画。这不是 bug,是可访问性规范的强制约束。
常见错误写法:<div class="drawer">...</div> —— 即使加了 role="navigation" 也不如原生 <nav></nav> 可靠。
-
<nav></nav>是唯一被所有主流屏幕阅读器识别为“导航区域”的语义元素 - 键盘 Tab 焦点进入后,会自动从第一个可聚焦子元素开始,无需额外
tabindex - 配合
aria-label="主菜单",能明确告诉辅助技术这是什么
transform: translateX(-100%) 比 left: -300px 更稳
用像素值写死 left: -300px 在响应式场景下极易失效:小屏宽度不足 300px 时,面板根本移不出视口;大屏下又可能留白太多。而 translateX(-100%) 始终相对于自身宽度计算,不依赖具体数值。
但要注意:必须搭配 position: fixed 或 absolute,否则 transform 会把页面其他内容挤动。
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 隐藏态:
transform: translateX(-100%); - 展开态:
transform: translateX(0); - 过渡声明必须写在基础类上(如
.drawer),不能只写在.drawer-open里 - 旧版 iOS Safari 对
translateX(-100%)渲染异常时,可用left: -100vw作兜底(非替代)
遮罩层 <div id="sidebar-overlay"> 必须和抽屉同级、独立定位
<p>很多人把遮罩写成抽屉的子元素,结果点击无效、层级错乱、或被父容器的 <code>overflow: hidden 截断。遮罩本质是全屏层,它和抽屉应是兄弟关系,都挂载在 下。
正确结构示例:
<body> <div id="sidebar-overlay"></div> <nav class="drawer"></nav> <main>...</main> </body>
- 遮罩样式必须含:
position: fixed; top: 0; left: 0; width: 100%; height: 100%; -
z-index设为 999,抽屉设为 1000,确保遮罩在下、抽屉在上 - 默认
pointer-events: none,打开时加pointer-events: auto才能响应点击 - 点击遮罩关闭抽屉,是用户强预期,别省略
移动端滚动锁定不能只靠 overflow: hidden
直接给 加 overflow: hidden 会导致页面“跳动”——滚动条消失后,body 宽度突然变宽,右侧内容右移。Safari 尤其明显。
更稳妥的做法是用 position: fixed 锁定 body:
- 展开抽屉时:
document.body.classList.add('no-scroll') - CSS 中定义:
.no-scroll { position: fixed; top: -${window.scrollY}px; width: 100%; } - 收起时恢复滚动位置并移除 class,否则后续页面无法滚动
- iOS 还需额外加
touch-action: none防惯性滚动穿透
这个细节容易被忽略:状态清理必须做,否则组件卸载后 body 仍被锁死,整个页面变不可滚动。


















