如何通过HTML实现符合WCAG的健壮性标准?
- 内容介绍
- 文章标签
- 相关推荐
本文共计842个文字,预计阅读时间需要4分钟。
健壮性(Robust)的核心是:
必须用对语义化标签,不能只靠div+ARIA
WCAG 2.1 AA 明确要求内容通过标准HTML Accessibility API Mappings暴露结构。这意味着:<nav>、<main>、<section>、<header>、<footer> 这些标签不是“可选装饰”,而是解析入口。屏幕阅读器靠它们构建导航树,而不是靠你写的 div + role="navigation"。
- ✅ 正确:
<nav><ul><li><a href="/home">首页</a></li></ul></nav> - ❌ 危险:
<div role="navigation"><div role="list"><div role="listitem"><a href="/home">首页</a></div></div></div>—— 多余嵌套、冗余role、丢失原生语义 - ⚠️ 注意:
<article>和<section>不可互换;<article>表示独立可分发内容(如博客正文),<section>是主题分组,乱用会导致屏幕阅读器朗读逻辑错乱
表单控件必须有合法的id和for绑定
健壮性要求表单控件与标签之间建立**可被解析的程序化关系**。仅靠视觉对齐或CSS定位无效。所有 <input>、<select>、<textarea> 必须满足以下任一条件:
- 显式
<label for="xxx">+<input id="xxx">,且id值全局唯一、无空格/特殊字符 - 隐式包裹:
<label>用户名<input type="text" name="username"></label> - 仅当完全无可见标签时,才退而使用
aria-label;但aria-labelledby优先于aria-label(因为它复用已有文本节点,更健壮) - 禁止:
<label>用户名</label><input id="user">(无for,无包裹,无ARIA)—— 屏幕阅读器无法关联
避免无效HTML和JS动态覆盖DOM结构
健壮性失效常发生在运行时。比如用 innerHTML 插入未转义的字符串,或用JS反复 removeChild/appendChild 破坏原有语义层级,都会导致辅助技术缓存失效或中断监听。
立即学习“前端免费学习笔记(深入)”;
- ❌ 危险操作:
el.innerHTML = "<button onclick=...>提交</button>"—— 若字符串含未闭合标签或非法嵌套,解析器可能截断或重排 - ✅ 推荐:
document.createElement("button")+el.appendChild(),确保节点类型合法、属性可控 - ⚠️ 特别注意:SSR渲染后由React/Vue做hydration时,若服务端HTML与客户端初始DOM结构不一致(如缺
alt、多嵌套div),部分屏幕阅读器会拒绝读取后续更新
本文共计842个文字,预计阅读时间需要4分钟。
健壮性(Robust)的核心是:
必须用对语义化标签,不能只靠div+ARIA
WCAG 2.1 AA 明确要求内容通过标准HTML Accessibility API Mappings暴露结构。这意味着:<nav>、<main>、<section>、<header>、<footer> 这些标签不是“可选装饰”,而是解析入口。屏幕阅读器靠它们构建导航树,而不是靠你写的 div + role="navigation"。
- ✅ 正确:
<nav><ul><li><a href="/home">首页</a></li></ul></nav> - ❌ 危险:
<div role="navigation"><div role="list"><div role="listitem"><a href="/home">首页</a></div></div></div>—— 多余嵌套、冗余role、丢失原生语义 - ⚠️ 注意:
<article>和<section>不可互换;<article>表示独立可分发内容(如博客正文),<section>是主题分组,乱用会导致屏幕阅读器朗读逻辑错乱
表单控件必须有合法的id和for绑定
健壮性要求表单控件与标签之间建立**可被解析的程序化关系**。仅靠视觉对齐或CSS定位无效。所有 <input>、<select>、<textarea> 必须满足以下任一条件:
- 显式
<label for="xxx">+<input id="xxx">,且id值全局唯一、无空格/特殊字符 - 隐式包裹:
<label>用户名<input type="text" name="username"></label> - 仅当完全无可见标签时,才退而使用
aria-label;但aria-labelledby优先于aria-label(因为它复用已有文本节点,更健壮) - 禁止:
<label>用户名</label><input id="user">(无for,无包裹,无ARIA)—— 屏幕阅读器无法关联
避免无效HTML和JS动态覆盖DOM结构
健壮性失效常发生在运行时。比如用 innerHTML 插入未转义的字符串,或用JS反复 removeChild/appendChild 破坏原有语义层级,都会导致辅助技术缓存失效或中断监听。
立即学习“前端免费学习笔记(深入)”;
- ❌ 危险操作:
el.innerHTML = "<button onclick=...>提交</button>"—— 若字符串含未闭合标签或非法嵌套,解析器可能截断或重排 - ✅ 推荐:
document.createElement("button")+el.appendChild(),确保节点类型合法、属性可控 - ⚠️ 特别注意:SSR渲染后由React/Vue做hydration时,若服务端HTML与客户端初始DOM结构不一致(如缺
alt、多嵌套div),部分屏幕阅读器会拒绝读取后续更新

