必须使用标签,因其是html5中唯一被规范定义为“导航链接集合”的元素,屏幕阅读器可识别为可跳转地标;其他标签如或无法替代其语义功能。

必须用 后台系统里大量存在 只有 用 别用 Bootstrap 的 正确结构是:把纯导航链接抽出来,独立成 重构顶部导航最容易被忽略的点,不是样式或交互,而是语义隔离是否彻底 —— 一个 <nav></nav>,不是 <div class="header-nav">,也不是 <code><header></header> —— 否则屏幕阅读器根本不知道这是导航。
为什么
<nav></nav> 不能被其他标签替代<div class="menu"> 或把整个页头塞进 <code><header></header> 的写法。这两种都错:<div> 没语义,辅助技术只读作“一个区域”;<code><header></header> 的语义是“页眉”,即使加了 role="navigation",原生语义仍优先,读出来还是“页眉”,不是“导航”。
<nav></nav> 是 HTML5 中唯一被规范定义为“导航链接集合”的元素,浏览器和屏幕阅读器会主动将其识别为可跳转地标,并在快捷键(如 NVDA 的 D 键)中单独列出。
<nav></nav> 必须配 aria-label,比如 <nav aria-label="主导航"></nav> 和 <nav aria-label="系统设置菜单"></nav>
<nav></nav> 内部不能再嵌套 <nav></nav>,否则可访问性树断裂,内层可能被忽略<nav></nav>
<nav></nav> 里的列表结构怎么写才对<ul></ul> + <li> + <a></a> 是标准且最稳妥的组合。它天然支持键盘 Tab 导航、语义层级清晰、无脚本时仍可点击,也方便后续用 CSS 控制布局(flex/column)或 JS 绑定事件。<div> 堆链接,也别省略 <code><li> 直接把 <a></a> 放进 <ul></ul> —— 这违反 HTML 规范,某些旧版读屏会跳过或误读。
aria-current="page",不能只靠 class="active"
aria-disabled="true" 并移除 tabindex,否则键盘用户能聚焦却无法触发aria-expanded 和 aria-controls,且值要与对应下拉容器的 id 匹配滚动时固定/隐藏顶部导航的 DOM 结构前提
data-spy="affix" 或现代 JS 实现(如 IntersectionObserver)都依赖正确的 DOM 层级。如果 <nav></nav> 被包在无语义的 <div> 里,或和 logo、搜索框混在一个 <code><header></header> 中,JS 就很难精准控制它的定位行为,更别说做无障碍适配。
<nav aria-label="主导航"></nav>,放在 <header></header> 内部或紧邻位置 —— 顺序不重要,但语义隔离必须干净。
<nav></nav> 包含非导航内容(如用户头像、搜索框),它们该属于 <header></header> 或独立容器<nav></nav> 元素本身,避免父容器 transform 或 overflow 隐藏导致 fixed 失效<button></button> 必须用 aria-controls 指向目标 <div class="collapse">,且该 <code><div> 不应放在 <code><nav></nav> 外部
<nav></nav> 里混进 logo、搜索、用户信息,或者用 <header></header> 顶替 <nav></nav>,都会让可访问性检查直接失败,且后续所有 JS 行为都可能偏离预期。











