必须包裹真实导航链接集合,全页仅能出现一次且不得被任何语义容器包裹;不可用替代,因其缺乏原生焦点管理、快捷键支持及旧版at兼容性,而或误将法律链接塞入均违反语义规范。

<nav></nav> 必须包裹真实导航链接集合,否则屏幕阅读器会跳过或误读为普通区块;<main></main> 全页只能出现一次,且不能被任何其他语义容器(包括 <header></header>、<footer></footer>、<section></section>)包裹——这是无障碍可访问性的硬性结构要求,不是建议。
为什么 <nav></nav> 不能用 <div role="navigation"> 替代
<p>两者在辅助技术中行为差异极大:<code><nav></nav> 是原生元素,浏览器自动赋予 role="navigation"、默认可聚焦、响应空格/回车激活、支持 NVDA/VoiceOver 的“跳转到导航区”快捷键(如 Ctrl+Option+U);而手动加 role 的 <div> 缺少内置键盘焦点管理,不带 <code>tabindex 时无法被键盘用户抵达,且 IE11 + JAWS 组合可能完全忽略该 role。
常见错误场景:
- 用
<div class="menu"> 包裹单个“返回首页”链接,误标为导航 <li>页脚的“隐私政策”“用户协议”列表被塞进 <code><nav></nav>—— 这些属于法律信息,不是导航,应放在<footer></footer>内用普通<ul></ul> - 面包屑写成
<nav><ol>...</ol></nav>却没加aria-label="面包屑",导致多个<nav></nav>无区分,屏幕阅读器无法识别用途 -
<div class="wrapper"> <header>...</header><main>...</main> </div>——<main></main>被无语义<div> 包裹,破坏其语义暴露 <li> <code><header>...</header><section><main>...</main></section>——<main></main>嵌套在<section></section>内,AT 无法准确定位主内容起始点 - SSR 渲染时,服务端注入的
<div id="root"> 把 <code><main></main>包在内部,等同于语义隔离正确结构应为:
<header>...</header><main>...</main><footer>...</footer>,中间不插入任何非语义容器。<label></label>关联失败的三个隐藏原因即使写了
<label for="email">邮箱</label><input id="email">,仍可能被屏幕阅读器跳过——问题常不在语法,而在执行环境。- ID 含非法字符:HTML ID 不允许
@、空格、中文等,如id="user-email@domain"会导致for失效;应改为id="user_email" - 动态生成缺失 ID:React/Vue 中未显式设置
id,或用Math.random()生成但未同步更新for值,造成绑定断裂 -
<label></label>内容为空或仅含空格:某些 AT(尤其是移动端 VoiceOver)会直接跳过该<label></label>,哪怕它已正确绑定
什么时候该放弃语义标签,退回
<div> <p>当语义标签强制引入隐含含义,而你的内容逻辑并不匹配时,硬套反而造成歧义。</p> <p>例如:</p> <ul><li>仪表盘里的“实时数据卡片”,既不是 <code><article></article>(不可独立分发),也不是<section></section>(无标题、非逻辑章节),用<div role="region" aria-labelledby="card1-title"> 更准确 <li>一个纯装饰性图标,没有交互、无文本替代,用 <code><img src="icon.svg" alt="">即可;若强行套<figure></figure>却不加<figcaption></figcaption>,反而让读屏软件困惑 - ID 含非法字符:HTML ID 不允许
-
<time></time>的datetime值格式错误(如写成"2025/09/12"或中文“2025年9月12日”),机器无法解析,此时不如用普通文本 + ARIA 描述
<main></main> 的 DOM 位置和嵌套陷阱
<main></main> 不是视觉居中容器,也不是样式 wrapper。它的语义前提是:直接包裹页面主体内容,且在整个 DOM 树中处于顶层逻辑层级。
典型失效结构:
语义标签不是越多越好,而是每个都得经得起“这个内容真的配得上这个标签吗”的拷问——尤其在动态渲染、组件化开发中,DOM 插入时机和属性同步稍有偏差,语义就彻底失效。











