Front-End Checklist 无障碍规则实战:修复role="text"容器中的可聚焦子元素
【免费下载链接】Front-End-Checklist🗂 The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist
导读
本文围绕 Front-End Checklist 仓库中的aria-text无障碍规则展开,系统讲解为什么role="text"容器内不应包含链接、按钮、输入框等可聚焦元素,以及如何在代码审查与前端审计中快速定位、修复并用浏览器无障碍工具验证此类问题。读完本文,你将掌握该规则的判定标准、修复手法、豁免场景,以及它在仓库中从 MDX 规则源到 Agent Skill 的完整实现链路,可直接用于日常开发与 AI 驱动的代码审查。
规则定位:一条关于"语义展平"的无障碍规则
aria-text规则的全称是Avoid focusable descendants in role="text" elements(避免role="text"元素包含可聚焦后代),在仓库中的元数据定义如下(见 packages/content/rules/en/accessibility/aria-text.mdx):
- 分类:accessibility(无障碍),子类
aria - 优先级:medium(中等)
- 难度:intermediate(进阶)
- 预计耗时:10 分钟
规则的核心原理一句话可以概括:给容器加上role="text"会强制屏幕阅读器把容器内的一切内容当作一段连续的纯文本字符串,从而"隐形化"其中嵌套的交互元素。role="text"主要用于 VoiceOver 特有的边缘场景,它只应该应用在纯静态文本容器上。WAI-ARIA 1.2 规范明确指出:一旦容器内出现交互内容,这种"子树展平"(subtree flattening)行为就会变得危险。
这条规则对应的 Skill 文档为 skills/aria-text/SKILL.md,详细实现说明与代码示例见 skills/aria-text/references/rule.md。仓库中的规则源 aria-text.mdx 是 Skill 文档的上游数据,二者内容一一对应。
为什么"文本展平"会成为无障碍黑洞
当屏幕阅读器遇到role="text"容器时,它会将整个子树合并为一个文本节点朗读。这意味着:
- 交互可见性(Interactive Visibility):容器内的链接、按钮等交互元素无法被屏幕阅读器用户聚焦和激活。用户虽然能在视觉上看到它们,但在读屏环境中它们完全"不存在"。
- 语义展平(Semantic Flattening):整个容器被拍平成单一字符串,子元素原有的语义(如
link、button角色)全部丢失。 - 用户困惑(User Confusion):视觉正常的用户看得到链接,屏幕阅读器用户却"看不见",两种用户的体验出现割裂。
- 键盘访问断裂(Keyboard Access):纯键盘用户或许仍然能用 Tab 键到达容器内的按钮,但屏幕阅读器不会正确播报它,形成"焦点到了、播报缺失"的割裂体验,用户不知道当前焦点落在什么控件上。
这种场景被形象地称为无障碍"黑洞"(accessibility black holes)——交互内容在辅助技术面前凭空消失。
代码示例:正确与错误的写法
以下是 skills/aria-text/references/rule.md 中给出的完整示例:
<!-- ✅ Correct: Simple text container --> <div role="text"> <span>Price: </span> <span>$10.00</span> </div> <!-- ❌ Incorrect: Contains a focusable link --> <div role="text"> Learn more at <a href="/details">this link</a> </div> <!-- ❌ Incorrect: Contains a focusable button --> <div role="text"> Submit your form <button type="submit">Submit</button> </div>正确的形态:role="text"容器只包裹纯静态文本,如价格标签Price: $10.00这类由多个 span 拼接的文本片段。此时展平语义是无害的,反而能保证读屏时数字与货币符号按预期连读。
错误的形态:一旦容器中出现<a>链接或<button>按钮这类可聚焦元素,展平就会把它们的可交互语义吞掉。两个错误示例分别对应"链接被藏匿"和"按钮被藏匿"两种典型事故。
修复手法
根据规则文档,修复只有两条路径:
- 移除
role="text":当容器需要承载交互子元素时,直接去掉role="text",让子元素恢复原生语义; - 把交互元素移出容器:如果确实需要某个文本容器保持
role="text",则将链接、按钮等交互元素挪到容器外部,避免嵌套。
修复的核心判断标准是:role="text"只容纳静态文本内容,不允许出现任何可聚焦后代(links、buttons、inputs 等)。
豁免场景:原生优先,不为 ARIA 而 ARIA
规则文档明确列出了三条例外(Exceptions),提醒审查者避免机械判罚:
- 优先使用原生 HTML 语义:能使用原生元素表达语义时就不要用 ARIA。很多看似 ARIA 失败的问题,在把底层元素修正为原生语义后就自然消失了。
- 缺失 ARIA 不一定是最高优先级发现:如果某个控件本身已经语义破损、没有可访问名称或键盘无法访问,那么"缺少 ARIA 属性"并不应该被当成最强的发现。
- 不要为了满足规则而硬加 ARIA:如果某个功能本应采用原生元素或更简单的交互模式,就不应该用 ARIA 去凑数。
这三条豁免共同指向一个原则:ARIA 是修复语义的工具,不是合规的遮羞布。审查时应先检查原生语义是否成立,再判断 ARIA 是否必要。
标准对齐
规则要求实现与以下标准保持一致,并且强调验证"渲染后的实际体验"而不只是源码本身:
- WAI-ARIA 1.2(无障碍富互联网应用规范,即
role="text"语义的权威来源); - MDN ARIA 文档(作为实现层面的参考)。
验证方法:从自动化到人工复测
规则文档提供了一套双层验证策略:
自动化检查
- 在浏览器的无障碍树(accessibility tree)或无障碍面板中检查相关元素、角色和可访问名称;
- 运行axe或Lighthouse等自动化无障碍检查工具,确认规则在渲染结果中成立。
人工检查
- 使用纯键盘导航测试受影响的 UI,确认规则在真实渲染体验中成立;
- 如果该规则影响关键交互,用屏幕阅读器重新走一遍代表性用户流程。
这里尤其值得注意:规则文档反复强调"验证渲染后的体验,而不仅是源码"——因为role="text"的展平行为是运行时的语义行为,静态看代码可能不容易发现交互元素的丢失。
仓库中的完整实现链路:从 MDX 规则到 Agent Skill
这条规则并不是孤立存在的,它在仓库中经历了一条完整的"规则源 → 生成脚本 → Skill 文档"流水线,理解这条链路对使用 Skill 的开发者与 AI Agent 都有帮助。
上游规则源
规则的权威数据源是 packages/content/rules/en/accessibility/aria-text.mdx。该文件的 frontmatter 除基本信息外,还定义了结构化字段,包括:
whyItMatters:规则的重要性说明(即"文本展平会隐藏交互元素");tldr:三条速查要点;prompts:check/fix/explain/codeReview四个面向 Agent 的提示词;aiContext:Agent 使用场景提示;sources:规范来源(WAI-ARIA 1.2 为主规范、MDN 为参考);relatedRules:关联规则清单,包括aria-hidden-focus、aria-command-name、aria-required-children、aria-treeitem-name,原因均为"同属 accessibility/aria 区域,通常一起审查"。
生成脚本
scripts/generate/generate-skills.ts 负责把每个规则的 MDX frontmatter 生成到skills/{slug}/目录下:
SKILL.md:由name、description、metadata与 Check / Fix / Explain / Code Review 四类提示词组装而成(对应 buildSkillMd);references/rule.md:规则正文经 MDX 语法剥离后转为纯 Markdown(对应 buildReferencesMd 与 stripMdxToMarkdown)。
从生成逻辑可以看出两个面向 Agent 的工程细节:
- description 必须满足 "Use when" 前缀约定:生成器会检查
aiContext或description是否以 "Use when" 开头(见 buildSkillMd),这是为了 skill 框架做 Agent 意图匹配。这就是 SKILL.md 中 description 以 "Use when reviewing rendered HTML..." 开头的原因; - description 最短长度约束:若不足 50 个字符,生成器会自动拼接规则标题补足(见 buildSkillMd)。
生成方式支持全量与增量两种:pnpm generate:skills生成全部规则,也可传入指定 MDX 文件路径(由 lefthook 在提交时调用)只重建变更的规则。
安装与使用
Skill 可独立安装:
# 安装全部 skills npx skills add frontendchecklist/skills # 只安装 aria-text 这一个 skill npx skills add frontendchecklist/skills --skill aria-text与 MCP 审计流程的衔接
在聚合型 Skill skills/frontend-checklist-global/SKILL.md 中,规则审查被编排进 MCP 工具工作流:先用review_code审查粘贴的代码或单个文件、用audit_url审计公开页面,再用search_rules、get_rule、fix_rule、explain_rule等工具(实现见 packages/mcp/src/tools)对具体问题给出精准修复建议。该 Skill 同时内置了保守的审查立场——只报告有直接代码证据支撑的问题,而不是罗列所有可能的增强项,这与本文规则的"豁免场景"精神一脉相承。
面向 Agent 的四个操作提示词
skills/aria-text/SKILL.md 为 AI Agent 定义了四步操作指引,开发者和 Agent 均可直接复用:
| 操作 | 提示词要点 |
|---|---|
| Check(检查) | 识别带role="text"的元素,确认其内部没有按钮、链接、输入框等可聚焦元素 |
| Fix(修复) | 从包含交互子元素的容器上移除role="text",或将交互元素移到容器外部 |
| Explain(解释) | 说明role="text"如何覆盖后代元素语义,使交互组件对读屏用户不可访问 |
| Code Review(代码审查) | 审查渲染后的标记与交互状态,精确定位违规的元素、角色、标签、焦点行为或键盘交互,并说明如何用浏览器无障碍工具或辅助技术验证修复 |
配合 skills/aria-text/references/rule.md 中的完整代码示例、豁免场景与双层验证方法,这条 Skill 可以作为一次完整、可执行的无障碍审计的最小单元。
小结
role="text"是一把双刃剑:在纯文本容器上它能改善读屏连读体验,一旦嵌套交互元素就会制造"视觉可见、读屏不可达"的黑洞。掌握 Front-End Checklist 的aria-text规则,意味着你既能准确判罚(可聚焦后代不可嵌套),又能理性豁免(原生语义优先、不为 ARIA 而 ARIA),还能完成从自动化工具到人工复测的闭环验证。在仓库中,这条规则以 aria-text.mdx 为数据源、以 SKILL.md 为 Agent 执行接口,是理解整个 Front-End Checklist 规则体系如何从"人类清单"转化为"机器可执行技能"的绝佳样本。
【免费下载链接】Front-End-Checklist🗂 The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考