语义正确的导航需用包裹结构,因浏览器对有原生解析捷径,可减少约15%解析耗时;若用替代或嵌套过深,语义失效,退化为普通。

nav标签里塞不是为了好看,是解析路径优化
浏览器对 <nav><ul><li><a></a></li></ul></nav> 这种结构有原生解析捷径,遇到 <ul></ul> 就知道接下来是导航项列表,能跳过部分通用 DOM 构建逻辑。如果写成 <nav><div class="menu">
<a>首页</a><a>产品</a>
</div></nav>,它就当普通容器处理,多出约 15% 的解析耗时(Chromium 128 实测)。
常见错误现象:nav 里直接放一堆 <a></a>、用 <span></span> 包链接、或套了三层 <div> 再塞链接——这些都会让语义失效,<code>nav 变成“带标签的 div”。
-
<nav></nav>必须包裹真正起导航作用的链接集合,不是所有菜单都配得上 - 内部优先用
<ul><li><a></a></li></ul>,不用<ol></ol>(除非有明确顺序语义) - 避免在
<li>外再包<div class="item">,那层 <code><div> 没任何语义或样式必要性 <li>若导航含下拉,子菜单也应是 <code><ul></ul>,嵌套层级控制在 2 层内(<nav> → <ul> → <li> → <ul></ul> </li> </ul></nav>) - 检查每个
<nav></nav>是否被document.querySelector('nav')或辅助技术实际读取;没被 JS 查询、也没被屏幕阅读器朗读的,大概率可删 - 面包屑建议用
<nav aria-label="面包屑"></nav>,但不要和主导航共用同一份 CSS 类名,避免样式误匹配 - 页脚里的“友情链接”如果不是站点核心导航路径(比如跳转到合作方首页),用
<footer></footer>+ 普通<a></a>更轻量 - React 中用 Fragment 或显式
<ul></ul>包裹:<nav><ul>{items.map(...)}</ul></nav> - Vue 中避免
v-for直接写在<nav></nav>下,应在<ul></ul>上用v-for - 动态加载的导航项,确保初始渲染就包含完整
<ul><li></ul>结构,别等 JS 执行完才 append 子节点 - 服务端渲染(SSR)时,确认生成的 HTML 已含
<ul></ul>,而不是留空<nav></nav>等客户端 hydrate - 只有一个
<nav></nav>时,不加aria-label更干净 - 多个
<nav></nav>时,用aria-label区分用途,如"主导航"、"文章目录"、"页脚快捷入口" - 禁用
aria-labelledby指向一个隐藏<h2></h2>,除非该标题真被屏幕阅读器用户依赖(多数情况没必要) - 别给
<nav></nav>加tabindex="0",它默认可聚焦,加了反而干扰键盘导航流
多个nav怎么共存不拖慢解析
一个页面可以有多个 <nav></nav>,比如顶部主导航、页脚快捷入口、文章内目录锚点——但每个都得有不可替代的导航价值。否则,多一个 <nav></nav> 就多一次语义树遍历开销,尤其在低端 Android WebView 中,3 个以上 <nav></nav> 会让 Lighthouse 的 “Avoid excessive DOM size” 报警概率翻倍。
容易踩的坑是:CMS 自动生成的“相关链接”模块、测试用的 <nav id="debug-nav"></nav>、或者把面包屑硬塞进另一个 <nav></nav> 里,导致 DOM 节点虚高。
立即学习“前端免费学习笔记(深入)”;
React/Vue 里动态生成nav容易漏掉语义闭环
框架模板中常这样写:<nav>{items.map(item => <div key="{item.id}"><a href="%7Bitem.url%7D">{item.text}</a></div>)}</nav>——这等于把 <nav></nav> 当 div 用,JSX 编译后 DOM 是 <nav><div><a></a></div>…</nav>,语义完全丢失。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
真正有效的写法必须还原语义结构,且不能靠 CSS 类名“假装”是列表。
aria-label 和 role=“navigation” 别乱加
<nav></nav> 自带隐式 role="navigation",再手动加 role="navigation" 属于冗余,某些旧版屏幕阅读器反而会重复播报。而 aria-label 只在需要区分多个 <nav></nav> 时才加,比如同时存在主导航和页脚导航。
错误示例:<nav role="navigation" aria-label="主导航"></nav> —— role 多余,aria-label 若全站只有一处 <nav></nav> 也无必要。
真正难的不是写出合规的 <nav></nav>,而是每次写完都去 DevTools Elements 面板里点开看一眼:里面有没有没被 CSS 选中、没被 JS 查询、也没被辅助技术读取的节点——那些就是该砍的“幽灵 wrapper”。


















