必须唯一且直接为body子元素,因其是屏幕阅读器和搜索引擎定位主内容的唯一语义锚点;嵌套或重复会导致at误判、seo降权及键盘导航失效。

为什么必须唯一且直接挂载在下
多个 <main></main> 会让屏幕阅读器无法判断“哪里是真正主内容”,尤其在 SPA 或多视图场景中,AT(辅助技术)可能只识别第一个或随机选一个。更麻烦的是,若 <main></main> 套在 <div> 或 <code><section></section> 里,语义会被降级为普通容器,失去“主内容区域”这一关键地标角色。
实操要点:
-
<main></main>必须是的直接子元素,不能嵌套在任何其他语义标签(如<section></section>、<article></article>)内 - 页面生命周期内只能存在一个
<main></main>;路由切换时,旧的要移除,新的要插入到底层,而非复用或仅 show/hide - 跳过链接(skip link)的
href必须指向这个唯一<main id="main"></main>,否则键盘用户 Tab 进去就卡在导航栏 - React/Vue 中不要用
display: none隐藏非当前<main></main>,而应彻底 unmount —— 否则 NVDA 仍会把它纳入可访问性树
nav、banner、complementary 这些地标怎么配才不冲突
HTML5 地标(landmark)不是“越多越好”。每个地标都有明确语义边界和使用意图,混用或错位会直接打乱 AT 的导航路径。比如把整个页眉塞进 <header></header>,再额外加 role="banner",反而让 VoiceOver 报两次“横幅区域”。
常见错误与修正:
-
<header></header>≠role="banner":前者是局部结构容器(如文章头部),后者是全局站点横幅,应只用于最顶层页眉,且建议显式写成<header role="banner"></header> -
<nav></nav>必须含真实导航链接,纯图标工具栏、筛选条件区、分页控件都不该用<nav></nav>—— 它们更适合role="region"+aria-label -
<aside></aside>不等于role="complementary":只有与主内容强关联、提供补充信息(如侧边术语解释、相关文章推荐)才用;广告位、无关社交按钮应设aria-hidden="true" - 避免无意义地标:比如给每个
<section></section>都加role="region",AT 会生成一堆“区域 1”“区域 2”,用户根本无法区分
ARIA-labelledby 和 aria-label 在地标中怎么选
地标本身不自带描述,AT 默认播报“导航区域”“主内容区域”这类泛化名称。用户需要知道“这是主导航”还是“这是文章侧边目录”,这就得靠 aria-label 或 aria-labelledby 显式标注 —— 但二者适用场景完全不同。
选择依据:
- 用
aria-label:当描述是静态短语,且无需 DOM 引用,例如<nav aria-label="主导航"></nav>、<aside aria-label="当前文章相关术语"></aside> - 用
aria-labelledby:当描述来自页面已有文本节点(如标题、说明段落),且需保持同步更新,例如<main aria-labelledby="page-title"></main>对应<h1 id="page-title">订单详情</h1> - 绝对不用
aria-label覆盖可见文本:比如按钮上写着“提交订单”,却设aria-label="确认下单",会造成读屏与视觉不一致 -
<nav></nav>和<main></main>必须带标识;<header role="banner"></header>建议带,<footer></footer>一般不用 —— 大多数 AT 默认忽略页脚地标
为什么跳过链接必须是 DOM 第一个可聚焦元素
跳过链接(skip link)的唯一作用,就是让键盘用户绕过重复导航块,直抵主内容。如果它不是 DOM 中第一个可聚焦节点,Tab 键一按就会先停在 logo、搜索框或语言切换器上 —— 这意味着“跳过”功能从一开始就没生效。
关键细节:
- 跳过链接必须出现在
开头,且顺序早于所有其他可聚焦元素(包括<a href></a>、<button></button>、tabindex="0"元素) - 默认隐藏要用
position: absolute; left: -999px;,不能用visibility: hidden或opacity: 0—— 后两者仍参与焦点流 - 获得焦点时必须用
:focus或:focus-visible触发显示,且样式要足够高对比度(WCAG AA 要求 4.5:1) - 目标锚点必须是语义化元素(
<main id="main"></main>),不能是<div id="main"> —— 否则某些 AT 会跳转失败或静默忽略 复杂布局里最容易被忽略的,是地标之间的嵌套关系和 DOM 位置刚性要求 —— 它们不像 CSS 那样能“灵活调整”,一旦结构错位,辅助技术就只能靠猜。</div>











