横向导航菜单必须兼顾结构、角色、状态和键盘行为:nav需配具体aria-label,菜单项用ul/li/a,当前页用aria-current="page",下拉菜单需button+aria-haspopup+焦点管理。

横向导航菜单光靠 float 或 flex 排列,不加语义和交互支持,对屏幕阅读器用户基本等于不可用。必须从结构、角色、状态、键盘行为四方面同步处理,缺一不可。
nav 必须配 aria-label,且不能写成 "Navigation"
只写 是无效的——它只是个容器标签,不是用途说明书。当页面存在多个 (比如主导航 + 面包屑 + 页脚链接),屏幕阅读器无法区分上下文。
常见错误包括:
-
:太泛,所有导航都叫 Navigation,等于没标 -
完全不加aria-label:NVDA/VoiceOver 通常只读“导航区域”,然后跳过,用户得手动摸索
正确做法是按实际功能命名:
菜单项必须用 ul/li + a 或 button,禁用 div + onclick
横向导航的本质是一组「可顺序访问的跳转目标」,:嵌套过深,破坏 内部语义流
正确结构示例:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
<nav aria-label="主导航"><ul>
<li><a href="/" aria-current="page">首页</a></li>
<li><a href="/about">关于</a></li>
<li><a href="/contact">联系</a></li>
</ul></nav>
当前页标识必须用 aria-current="page",别删 href 或加 disabled
“当前页”不是禁用状态,而是语义终点。用 aria-disabled="true" 或移除 href 会直接导致键盘用户无法聚焦、读屏跳过、或误报“已禁用”。
必须做到:
- 保留
href(哪怕指向当前 URL),确保可聚焦、可回车触发(JS 可拦截) - 仅在当前页链接上加
aria-current="page",值不能是"true"或"active" - 不要给整个
加aria-current,它只作用于具体链接元素 - 视觉样式可用
color: #007bff; font-weight: bold;等,但不能靠 display: none / visibility: hidden 隐藏
下拉子菜单需额外处理焦点流与 aria-expanded
纯 :hover 触发的下拉菜单,在键盘模式下完全失效。必须补全键盘交互逻辑:
- 主菜单项用
替代,并加aria-haspopup="menu"和aria-expanded="false" - 子菜单
加role="menu",每个子项用或 - 用 JS 监听
Enter/Space切换展开状态,并同步更新aria-expanded - 用
focusout+setTimeout实现“离开即收起”,避免焦点丢失后菜单悬空 - 移动端需额外监听
touchstart并阻止默认行为,防止双击放大
最易被忽略的是:子菜单打开后,焦点必须自动移到第一个可交互项;关闭后,焦点应回到触发按钮。否则键盘用户会卡在空白区域。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










