main 必须唯一,否则屏幕阅读器“M键跳转”失效;section需带h2–h6标题,article须能独立存在并被RSS抓取;header/nav/footer被div包裹通常无害,但不可嵌入table或ul内部;标题层级须连续,h1全局建议仅用一次。

main 必须唯一,否则屏幕阅读器“M键跳转”直接失效
辅助技术(如 NVDA、VoiceOver)把 main 当作页面的语义锚点:用户按 M 键,工具会跳过所有 nav、header、aside,直抵 main 起始位置。但 HTML 规范明确要求全 DOM 中只能有一个 main,且它必须代表“当前最需要操作/阅读的核心内容”。
常见崩坏场景:
- Next.js 布局组件里写了一个
main,子页面又套一个——浏览器通常只认第一个,第二个被忽略;用户从首页跳进详情页,M 键仍停在旧位置 - 微前端子应用在
iframe中自行声明main,脱离主文档上下文,辅助技术无法将其纳入整体可访问性树 - 把顶部 banner、左侧菜单、广告位全塞进同一个
main,导致“主要内容”被稀释,读屏工具播报时堆砌无关信息
section 和 article 不是 div 的高阶替代品,滥用会污染大纲
section 和 article 解决的不是布局问题,而是文档大纲(outline)和内容可分发性。它们不提供额外样式或行为,只影响辅助技术对内容层级和独立性的判断。
判断依据极简:
立即学习“前端免费学习笔记(深入)”;
-
section必须自带<h2>–<h6>标题;没标题?用div -
article要能独立存在:删掉周围所有内容后仍语义完整;能被 RSS 抓取、邮件推送、聚合页引用;否则别硬套 - 错误示例:
<section><p>欢迎关注我们</p></section>——无标题、不可分发、无结构意义,纯属污染大纲
header/nav/footer 被 div 包裹一般无害,但 table/ul 内嵌语义标签会破坏 HTML 有效性
对于 header、nav、footer 这类块级语义标签,被 div 包裹通常不影响辅助技术识别——DOM 中语义未丢失,可访问性树仍能正确构建。
但以下嵌套绝对禁止:
-
main或nav嵌套在<table>里:HTML 无效,浏览器可能丢弃整个节点,NVDA 直接跳过该区域 -
nav放在<ul>内部(而非包裹ul):违反ul子元素只能是li的规范,导致结构解析失败 -
fieldset被div包裹后再设role="group":它必须是直接父容器,否则legend无法关联输入框,JAWS 可能完全忽略分组标题
标题层级断裂会让屏幕阅读器导航失效
辅助技术依赖 h1–h6 构建内容大纲,用户可通过快捷键(如 NVDA 的 H 键)按层级跳转。一旦出现跳级或重复,导航逻辑就乱了。
典型错误:
- 在
main内部先用<h2>,再突然插入<h1>:标题层级断裂,读屏工具可能重置上下文或跳过后续内容 - 多个
h1并存(尤其 SSR 渲染时动态插入):部分旧版 VoiceOver 会只朗读第一个,其余静默 -
section内部用<h1>:应统一用<h2>或更低级,保持连续性;h1全局建议仅用一次,代表页面主主题
真正难的不是记住规则,而是把语义判断嵌入日常编码习惯——比如写完一个区块,下意识问自己:“这个内容删掉周边后还能独立存在吗?”、“用户按 M 键进来,看到的是不是他此刻最需要的东西?”



















