标签本身声明导航区域,但需配合aria-label才能让屏幕阅读器区分多个导航区;若仅用不加aria-label,屏幕阅读器仅播报“导航区域”而无法说明类型,且多个共存时漏标任一aria-label会导致该区域对辅助技术“不可见”。

用 <nav></nav> 而不是 <div class="nav"> 包裹导航栏
<p>屏幕阅读器会把 <code><nav></nav> 当作一个独立的导航区域,自动播报“导航”并允许用户快速跳转;而纯 <div> 没有语义,它只会读成“分区”,甚至可能被完全忽略。<ul>
<li>如果页面有多个导航区(比如顶部主菜单 + 页脚快捷链接),给每个 <code><nav></nav> 加 aria-label 区分:
<nav aria-label="主菜单"></nav>
<nav aria-label="页脚资源"></nav>
<nav></nav> —— 它是顶级语义容器,嵌套会导致屏幕阅读器混淆层级<nav></nav> 内部必须包含至少一个可聚焦的链接(<a href></a> 或 <button></button>),否则部分阅读器会跳过整个区域为所有交互控件提供键盘焦点和 role 明确性
<div onclick="submit()"> 看起来能点,但键盘用户按 <code>Tab 无法到达,屏幕阅读器也读不出它是“按钮”。
- 替换方案只有两个可靠选择:
<button type="button"></button>(原生按钮,自带焦点、空格/回车触发)<a href="#"></a>(带href的链接,可聚焦,需阻止默认跳转) - 如果必须用
<div>(比如复杂组件封装),则必须同时满足:<br> 添加 <code>tabindex="0"
添加role="button"(或role="link")
手动监听keydown处理Enter和Space - 切记:加了
role不等于有了行为,role="button"不会自动响应空格键,必须自己写事件逻辑 - 页面必须且只能有一个
<main></main>,且它应包裹核心内容(非侧边栏、非广告位) -
<section></section>需要配合aria-labelledby或<h2></h2>等标题级元素,否则阅读器只读“区域”,不说明“这是什么区域” -
<aside></aside>适合放相关但非主线的内容(如文章侧边术语解释),不适合放广告或无关推荐——那该用<div> 并明确标注 <code>role="complementary"图片、图标、空元素必须带
alt或aria-hidden<img src="logo.png">在没有alt时,NVDA 会读出文件名,VoiceOver 可能直接跳过或报“图像”,用户完全不知道是什么。- 有意义的图:写描述性
alt,比如<img src="chart.png" alt="2025年Q1营收同比增长12%"> - 装饰性图 / 图标(如按钮里的小箭头):用
alt=""(空字符串),或aria-hidden="true"+role="presentation" - SVG 图标:如果内联,需加
aria-hidden="true",并在父容器(如<button></button>)里写清楚文本内容,不要依赖图标本身传达信息
真正卡住人的往往不是“要不要做 A11Y”,而是“某个
<div> 到底该加 <code>role还是换标签”“alt写太长会不会影响体验”。这些判断没有银弹,得看它在语音流里怎么被读出来、键盘流里怎么被抵达。 - 有意义的图:写描述性
<main></main> 和 <section></section> 不是装饰标签,它们是跳转锚点
屏幕阅读器用户常用快捷键(如 JAWS 的 Insert + F6)直接跳到 <main></main>,绕过重复的导航和页眉。如果漏掉或错用,等于关掉了“快进键”。











