nav标签仅在包裹真实跳转链接、结构合理且DOM可访问时才具语义化作用;空导航、伪链接、嵌套或动态未就绪的<nav>均无效,须用aria-label区分多导航并避免滥用。

nav 标签不是“写了就起作用”的装饰性标签,它只在包裹真实跳转链接、结构合理、DOM 可访问时才被浏览器和读屏器识别为导航区域。空 nav、伪链接、嵌套或未就绪的动态内容,都会导致语义失效。
什么时候必须用 nav?
仅当链接组构成站点级或应用级的**主要导航区块**时才适用:
- 顶部横栏主导航(如「首页|产品|文档|博客」)
- 侧边垂直菜单(后台系统功能入口、文档目录)
- 响应式汉堡菜单展开后的真实链接集合
- 分页控件(
<a href="/page/2">下一页</a>这类带有效href的跳转)
常见误用:上一篇/下一篇、文章内「参见」链接、页脚版权条款链接——这些应归入 section 或普通 a,不构成主导航。
nav 里能放什么?不能放什么?
核心原则:只放**可跳转、可聚焦、有语义目的的导航目标**。
立即学习“前端免费学习笔记(深入)”;
- ✅ 推荐结构:
nav→ul→li→a href="..." - ✅ 单个简单导航可用:
nav→a+a(但至少两个链接,单个a不构成“集合”) - ❌ 禁止:
button、span、p、form(搜索框若非导航流程一部分,应移出) - ❌ 避免混入 logo、登录按钮、分享控件——它们属于交互操作,不是导航目的地
特别注意:nav 内部不能嵌套另一个 nav,HTML 规范明确禁止嵌套。
多 nav 共存时怎么区分?
同一页面多个 nav 必须靠 aria-label 显式声明用途,否则屏幕阅读器会重复播报“navigation”,用户无法判断哪个是主菜单、哪个是页脚快捷入口。
- 主导航:
<nav aria-label="主导航">... - 文章目录:
<nav aria-label="本文目录">... - 页脚链接:
<nav aria-label="页脚快捷链接">... - 面包屑可接受:
<nav aria-label="当前位置">,但更推荐ol+aria-label
不要用 title 属性替代 aria-label —— 它不被键盘/语音用户可靠识别。
动态渲染的 nav 怎么确保语义生效?
React/Vue/AJAX 加载的导航,初始 DOM 中若为空或仅含 loading 占位符,读屏器会直接跳过该区域。语义成立的前提是:首次渲染完成时,nav 内已存在可聚焦、可点击的 a 节点。
- CSR 场景下,至少预置一个占位链接(如
<a href="/">首页</a>),再异步替换完整菜单 - 验证方法:打开控制台执行
document.querySelector('nav a'),返回非null才算就绪 - SSR/SSG 天然满足条件,无需额外处理
- 避免用外层容器做状态控制(如
v-if="menuLoaded"),应让nav始终存在,仅内部节点动态更新
最容易被忽略的点是:语义不取决于你写了几个 nav,而取决于它在 DOM 中是否**真实承载了可访问的跳转能力**——没链接的 nav 就是无效的壳子。



















