用途:在样式、脚本或 ARIA 补丁之前,确定应存在哪种 HTML 结构,使浏览器、辅助技术、爬虫、表单与测试都能依赖。优先选择内置契约与用户动作匹配的原生元素,仅在原生 HTML 无法表达时添加 ARIA,并测试渲染后的契约。
边界:本技能负责元素选择与文档结构(按钮与链接、标题、地标、标签、表格、列表、嵌套及原生 disclosure/dialog/form 语义);a11y-contract-testing 负责渲染后的 role/name/state/focus 测试;constraint-validation-contracts 负责原生有效性生命周期;design-to-code-fidelity 负责语义修复可能引起的视觉间距与顺序偏移。
审查要点:动作语义,避免假禁用链接仍可导航、假禁用按钮仍可聚焦,div-onClick 与 href="#" 属于缺陷模式;标题层级,级别表达章节顺序而非字号,重复卡片不应产生顶层标题噪声;地标,每页一个主 main,仅在有助导航时命名区域;表单,除程序化标签外,在用户需要据此修正输入时用 aria-describedby 关联错误/帮助文本,相关单选/复选框用 fieldset/legend 分组;集合与数据,重复同级项用列表,二维数据用带行列标题的表格,div 网格仅当组件提供完整网格契约与测试;水合与解析器稳定性,检查浏览器在 React/Vue/Svelte 水合前静默修复的非法嵌套,如段落含块级元素、交互元素嵌套交互元素。
缺陷模式:带 onClick 和 tabIndex 的 div/span 缺少键盘/表单/禁用语义,应用 <button type="button"> 或真实链接;href="#" 的命令链接应改用按钮,仅真实 URL 用链接;卡片整体一个链接加内部操作按钮会造成交互目标歧义,应分离链接区与操作按钮;视觉标题用粗体文本会丢失标题结构,应用正确标题级别再样式化;仅用 placeholder 作标签会在输入后消失,应用可见标签或稳定程序化标签;用 ARIA role 修复原生不匹配可能产生更差或重复语义,应先改原生元素再测试。
快速探测(仅作线索,提交前检查渲染输出):rg -n '<(div|span)[^>]\bon[A-Z][a-z]+=|<(div|span)[^>]\bonclick=' src/ app/ packages/ 2>/dev/null;rg -n 'role="(button|link|heading|list|listitem|checkbox|tab|dialog)"' src/ app/ packages/ 2>/dev/null;rg -n '<h[1-6][^>]*class=|</?[bi]>' src/ app/ packages/ 2>/dev/null;rg -n '<main\b|role="main"|<nav\b|<header\b|<footer\b|<aside\b' src/ app/ packages/ 2>/dev/null。
纳入 PR 的门槛:仅当元素参与导航、命令、表单输入、章节结构或数据解读的用户可见契约,当前标记缺少或违背原生契约,且改动小的原生元素/结构可保持行为,或剩余自定义模式有明确 a11y 测试跟进时,才计入发现。应拒绝:无交互的装饰性包装本身不是语义缺陷;具有正确隐式角色的原生元素不需要冗余 ARIA;对标题字号的设计偏好不是层级缺陷;无头组件可能在可见文件外提供语义,声称契约破坏前应检查渲染输出。
输出结构:每个发现包含标记契约(期望的原生结构)、证据(文件/行或渲染 DOM)、风险(可能失败的用户/测试/浏览器行为)、修复(最小结构改动)、跟进(a11y-contract-testing、视觉检查或水合检查)。来源参考 HTML Living Standard、W3C ARIA in HTML、W3C WAI-ARIA Authoring Practices Guide 与 MDN;旧 HTML 大纲算法从未实现并已于 2022 年从规范移除,h1–h6 逻辑顺序传达结构。