标签仅在包裹真实跳转链接、结构清晰且DOM可访问时才具语义,必须含至少两个有效,禁用伪链接、表单、搜索框等非导航内容,多须用aria-label明确区分用途。

nav 标签不是“加个标签就完事”,它只在包裹真实跳转链接、结构清晰、DOM 可访问时才生效。空的、伪链接的、混入非导航内容的 nav,浏览器和屏幕阅读器会直接忽略。
nav 里必须放什么,否则语义失效
语义不来自标签名,而来自它包裹的内容是否符合“主导航”的行为预期:
- 必须包含至少两个以上真实
<a href></a>链接,且href值可被解析(如href="about.html"、href="/contact"、href="#features") - 推荐用
<ul><li><a></a></li></ul>结构——读屏器能报“列表,共 4 项”,平铺<a></a><a></a>会被当成无序文本流 - 允许包含
aria-current="page"的当前页标识,但不能只有这个属性而无其他可跳转链接 - 禁止塞入:
<form></form>、<input>、logo 图片、语言切换按钮、搜索框、纯文本说明
多个 nav 共存时怎么区分用途
页面可以有多个 nav,但每个都得有明确角色,否则辅助技术无法判断优先级或跳转意图:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 用
aria-label显式标注,例如:<nav aria-label="主导航"></nav>、<nav aria-label="页脚快捷入口"></nav> - 避免泛称如
aria-label="导航"或aria-label="菜单"——这些词对屏幕阅读器用户毫无区分度 - 如果某个
nav有可见标题(比如<h2 id="related-nav">相关栏目</h2>),可用aria-labelledby="related-nav"替代aria-label - 不要嵌套
nav:二级下拉菜单应通过<ul><li><ul></ul></li></ul>实现,而非<nav><nav></nav></nav>
为什么用 nav 而不是 div 包导航栏
这不是“写法偏好”,而是功能刚需。不用 nav 会导致实际可访问性断裂:
立即学习“前端免费学习笔记(深入)”;
- 键盘用户按
Alt+F1(Chrome)或Insert+F7(NVDA)无法一键跳入导航区 - 屏幕阅读器默认跳过纯
div包裹的链接列表,用户得逐个Tab才能摸到第 1 个链接 - Lighthouse 会报错
Navigation landmark not present,影响无障碍评分 - 搜索引擎可能弱化该区域链接的路径权重,导致“关于我们”“服务”等页收录变慢
- 即使你用 CSS 把
div.nav样式做得一模一样,语义层仍是空白
容易被忽略的 DOM 状态陷阱
最常出问题的地方不在写法,而在运行时状态:
- JS 动态渲染导航后,若未等链接节点插入 DOM 就结束初始化,
document.querySelector('nav a')会返回null——此时nav对辅助技术就是空的 - 用
href="#"+ JS 拦截跳转,右键“在新标签页打开”失效,且键盘用户无法用Enter触发,属于 WCAG 违规 -
nav放在<main></main>或<footer></footer>里完全合法,但若放在display: none或visibility: hidden容器中,语义即刻失效 - 固定定位的
nav若没设scroll-margin-top,锚点跳转后目标元素可能被遮挡,用户看不到内容


















