不是装饰,而是结构必需:必须用包裹语义结构,配aria-label明确导航意图,禁用div class="nav"等伪语义写法,否则屏幕阅读器无法识别导航地标、seo降权、键盘导航错乱。

<header></header> 和 <nav></nav> 不是可选装饰,而是结构必需——用 div 套 class="header" 或 class="nav",等于把语义关在门外。浏览器、爬虫、屏幕阅读器只认标签名,不读 class 名。
为什么 div class="nav" 是无效的「导航」
辅助技术(如 NVDA、VoiceOver)不会因为 class 名叫 "nav" 就把它当导航处理;它只会跳过或误判为普通容器。真正触发「导航地标(navigation landmark)」的是原生 <nav></nav> 标签。
- 错误写法:
<div class="nav">@#@#@#@#@#@#@#@#@#@0@#@#@#@#@#@#@#@#@#@1</div>→ 无 landmark,无 ARIA role,SEO 不识别导航意图 - 正确写法:
<nav aria-label="主导航"><ul> <li>@#@#@#@#@#@#@#@#@#@0</li> <li>@#@#@#@#@#@#@#@#@#@1</li> </ul></nav> -
aria-label不是可选:多个<nav></nav>时(比如页脚也有链接组),必须用aria-label区分作用,否则屏幕阅读器用户无法分辨“这是顶部菜单还是底部快捷入口”
<header></header> 能嵌套 <nav></nav>,但不能被 div 包裹
<header></header> 天然是 sectioning root,自带隐式 role="banner",且影响文档大纲生成。一旦用 div 包一层再加 class,就切断了这个语义链。
- 反例:
<div class="header"><nav>...</nav></div>→<nav></nav>失去上下文,div不参与 outline 算法 - 正例:
<header><h1>漫步时尚广场</h1> <nav aria-label="主导航">...</nav></header> - 注意:
<header></header>可以有多个(如每个<article></article>自带标题区),但页面级<header></header>通常只出现一次,且应直接位于下(非<main></main>或其他 sectioning content 内)
导航链接必须用 ul/li,不是为了样式,而是为了语义
屏幕阅读器默认按列表项(listitem)播报导航,若用 span 或 div 平铺链接,会连读成一长串无停顿文本,用户根本无法定位。
- 必须用
<ul><li><a>...</a></li></ul>结构,哪怕 CSS 重置了所有默认样式 - 避免
<nav><a>首页</a><a>产品</a></nav>—— 这种写法缺失列表语义,Lighthouse 会报「导航缺少列表结构」 - 如果导航含下拉菜单,用
<details><summary></summary></details>或 ARIAmenu模式,但顶层仍需保持ul/li基础结构
<main></main> 必须紧邻 <header></header>,且不能被任何容器隔开
常见重构失败点:把 <main></main> 放进 <div class="container"> 里,结果导致它不再是 <code> 的直系子元素,从而被排除出 landmark 列表,Lighthouse 直接扣分。
- 合法结构:
<header>...</header><main>...</main><footer>...</footer> - 非法结构:
<div class="wrapper"> <header>...</header><main>...</main> </div>→<main></main>被包裹,语义降级 - 解决办法:把布局类(如
container)直接加在<header></header>、<main></main>、<footer></footer>上,而不是额外套一层div
最容易被忽略的其实是层级真实感:一个 <header></header> 里放了 <h1></h1>,但 <main></main> 里却用 <h3></h3> 开头——这会让大纲断裂,屏幕阅读器用户听不出主次。语义不是贴标签,是让结构自己说话。











