原生HTML5地标标签(如<nav>、<main>)已自带正确ARIA role,显式添加role不仅不必要,还易引发landmark-is-unique等可访问性错误;应优先使用语义化结构、明确命名,并通过Chrome DevTools Accessibility Inspector验证Computed Role、Name和States。

直接用 <header>、<nav>、<main>、<aside>、<footer> 这些原生标签,就已满足绝大多数地标角色需求;显式加 role 不仅不必要,反而容易触发 landmark-is-unique、landmark-no-label 等可访问性错误。
Chrome DevTools Accessibility Inspector 怎么快速验证地标是否生效
不用装插件、不跑 CLI,Chrome 自带的 Accessibility Inspector 就能实时看地标是否被正确识别。打开方式:Mac 按 Cmd+Shift+P,Win/Linux 按 Ctrl+Shift+P,输入 “Accessibility” 回车;或右键任意元素 → Inspect Accessibility Properties。
重点盯三列:
-
Computed Role:它实际被辅助技术当成什么(比如<nav>应显示navigation,若显示generic,说明被display: none或visibility: hidden隐藏了) -
Name:屏幕阅读器读出的名称(为空即触发landmark-no-label) -
States:如expanded、hidden是否同步(尤其对role="search"或role="region"类容器)
为什么给 <nav> 加 role="navigation" 反而报错
HTML5 原生标签自带隐式 ARIA role:<nav> 默认就是 role="navigation",<main> 默认是 role="main",<footer> 是 role="contentinfo"。W3C 明确要求“不要改写原生语义”,除非你在 polyfill 旧浏览器。
立即学习“前端免费学习笔记(深入)”;
常见错误现象:
- 多个
<nav>元素都未加aria-label或aria-labelledby→ 全被读成“导航区域”,用户无法区分主导航、面包屑、页脚链接 - 用
<div role="main">替代<main>→ 可以,但必须确保全局唯一,重复会触发landmark-is-unique - 给
<section>加role="region"却没配aria-label→ 直接报landmark-no-label
表格里加筛选行时,role="search" 为什么总报 aria-requires-children
这不是你漏写了子元素,而是你把 role="search" 错加在了 <tr> 上。HTML 中 <tr> 的隐式 role 是 row,<th> 是 columnheader,<td> 是 cell。一旦给 <tr> 加 role="search",它就不再是表格行,而变成一个独立的 landmark,导致其父 <thead> 下出现非法子元素(search 不在 <thead> 允许的子元素列表里)。
修复方法极其简单:
- 删掉所有加在
<tr>、<th>、<td>上的role声明 —— 它们全是多余的,且有害 - 保持原生表格结构,在每个
<input type="search">上加aria-label="按姓名筛选" - 避免用
aria-labelledby指向表头文字复用名称 —— 筛选控件和表头语义不同,用户需要明确知道“这是筛选框”,不是“这是列名”
<input type="search"> 为什么不能加 role="search"
role="search" 是给整个搜索区域(比如包含输入框、按钮、筛选项的 <section> 或 <div>)用的,不是给 <input> 本人加的。强行加在 <input> 上,会覆盖它原本由 type="search" 自动提供的 role="searchbox",导致屏幕阅读器误读为“一个叫 search 的容器”,而不是“一个可输入的搜索框”。
正确做法是:
- 用
<input type="search">,它已自带role="searchbox"和基础无障碍支持 - 必须包裹在
<form>中(哪怕 JS 拦截提交) - 必须设
name="q"(行业惯例,后端和 SEO 友好) - 必须用
aria-label或aria-labelledby提供名称 ——placeholder不能替代 - 若需独立地标语义,用
<section role="search">包一层,再把<input type="search">放进去
最易被忽略的是:地标角色不是靠堆 role 实现的,而是靠结构清晰 + 名称明确 + 原生语义优先。一旦开始手动加 role,就得同步处理焦点、键盘事件、状态同步和屏幕阅读器反馈 —— 否则只是贴了一张失效的标签。



















