关于 forms
forms 是用于实现或审查表单、输入控件和验证流程的可访问性技能。它指导表单标签、错误反馈、认证和提交等环节,并建议优先采用原生 HTML 控件。
主要功能
- 01控件标签与错误关联
- 02错误摘要和焦点移动
- 03输入类型与自动填充
- 04认证及粘贴支持
- 05提交与异步状态反馈
适用场景
- 01审查表单标签和验证错误提示
- 02改进登录与验证码输入流程
- 03检查提交后的状态通知和错误恢复
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mgifford/ accessibility-skills --skill forms安装后在 Claude Code 中输入/forms确认已加载。
附带文件SYNC.md
详细介绍
表单无障碍技能
规范来源:
mgifford/ACCESSIBILITY.md中的examples/FORMS_ACCESSIBILITY_BEST_PRACTICES.md此技能源自该文件。如有疑问,请以示例为准。
实施或审核任何表单、输入或验证流程时,请遵循以下规则。 仅当项目包含表单时,才加载此技能。
核心要求
表单必须便于用户使用键盘、触控、语音输入、屏幕阅读器、屏幕放大功能、浏览器自动填充、密码管理器及其他辅助技术理解和操作。这些要求适用于初始输入、验证、恢复、检查、提交和身份验证。如果时间限制并非必要,用户必须能够完成有时限的表单;用户还必须能够在 200%/400% 缩放下完成表单,且不会丢失内容或功能。
优先使用原生 HTML 控件。只有当原生控件无法满足已记录的要求时,才构建自定义控件,并实现适用的键盘、焦点、名称、角色、状态和值行为。
严重程度等级(本技能)
| 等级 | 含义 |
|---|---|
| 严重 | 完全阻碍一个或多个残障群体完成任务 |
| 较高 | 严重影响访问;不能指望用户通过合理的变通方式解决 |
| 中等 | 造成不便;存在负担不大的变通方式 |
| 轻微 | 未达到最佳实践;对访问的影响很小 |
不要仅根据违反的规则判定严重程度,而应根据实际表单和任务来确定。请考虑:缺陷是否会阻碍提交或恢复;是否影响身份验证、支付、医疗、法律、安全或基本公共服务;受影响的用户或控件有多少;是否存在合理的变通方式;缺陷是否源自共享组件;以及数据是否可能丢失。
严重:标签
每个表单控件都必须有以编程方式关联的标签。 缺少标签属于严重问题——屏幕阅读器用户无法识别字段。
- 切勿将占位符文本用作唯一标签——输入内容后占位符会消失,也不符合对比度要求,且并非所有屏幕阅读器都能可靠地读出
- 必填字段必须通过文本标明,不能仅用颜色区分
- 将控件嵌套在自己的
<label>中也是有效做法 - 只有在实际情况下无法使用可见的 HTML 标签时,才使用
aria-label/aria-labelledby;并确保无障碍名称包含用户能看到的文字(语音输入用户会根据可见标签识别控件) - 内容本身已提供名称的控件(例如,
<button>Save</button>)无需单独的标签
<input type="email" placeholder="Email address">
<label for="email">
Email address <span class="visually-hidden">(required)</span>
</label>
<input type="email" id="email" autocomplete="email" required>
关于 aria-required: 对已具有 HTML required 属性的原生输入控件,不要添加 aria-required="true"——这是冗余的,会给无障碍树增加噪声。仅当自定义控件(例如,role="combobox"、role="listbox")无法使用原生属性时,才使用 aria-required。
必填/选填字段: 在第一个字段之前说明如何识别必填字段(例如,“必须填写标记为‘必填’的字段”)。不要只依赖星号或颜色。如果标记较少的必填字段更清晰,就不要标记每个选填字段;反之亦然。
严重:错误识别
必须以编程方式将错误与对应字段关联。 缺少错误识别属于严重问题——盲人用户无法得知存在问题。
- 验证确定字段无效后,为其添加
aria-invalid="true";用户更正后,移除无效状态和错误关联 - 错误消息必须具体且可操作,不能只写“输入无效”
- 切勿仅使用颜色或图标来表示错误
- 通过
aria-describedby(或经过测试的aria-errormessage实现)将错误消息与字段关联;保留任何现有提示关联 - 除非出于安全需要,否则保留用户输入的值
<label for="email">Email address</label>
<p id="email-hint">We will send the receipt to this address.</p>
<input id="email" name="email" type="email" autocomplete="email"
aria-invalid="true" aria-describedby="email-hint email-error">
<p id="email-error">
<strong>Error:</strong> Enter an email address in the format [email protected].
</p>
不要对页面加载时就已存在的错误文本添加 role="alert"——实时区域只会播报其建立之后发生的更改。未经辅助技术测试,避免同时使用多种相互竞争的播报机制。
严重:错误摘要
当多个字段可能出错、表单较长、错误可能位于视口之外,或用户难以定位错误时,请提供错误摘要。对于存在多个错误、较长或复杂的表单,缺少错误摘要属于严重问题。
<div id="error-summary" tabindex="-1" aria-labelledby="error-heading">
<h2 id="error-heading">There are 2 errors</h2>
<ul>
<li><a href="#email">Email address: enter a valid email address</a></li>
<li><a href="#dob-day">Date of birth: enter a real date</a></li>
</ul>
</div>
- 将摘要放在表单前面或表单开头;提交失败后插入摘要,并将焦点移至摘要
- 使用能够说明字段和问题的链接;激活链接时,必须将焦点移至相应控件
- 保留字段内联消息和摘要;错误更改时更新标题中的错误数量
- 如果移动焦点已经能清晰地播报错误,避免添加
role="alert",除非测试表明额外的实时播报有所帮助 - 移动焦点是对提交操作的有意响应——不要在每次内联验证更改时都移动焦点
严重:不要阻止粘贴
切勿阻止任何输入控件中的粘贴、复制或标准键盘操作。 阻止粘贴属于严重问题——有运动障碍的用户以及密码管理器用户无法重新输入他们无法亲自键入的凭据。
高风险:无障碍身份验证(WCAG 3.3.8)
除非提供符合要求的替代方案或辅助机制,否则身份验证不得要求用户记忆、处理或转录信息。 至少应做到:
- 允许密码管理器识别并填写用户名和密码字段
- 允许在用户名、密码和验证码字段中复制和粘贴——不要将一次性验证码拆分到无法粘贴完整验证码的多个控件中
- 不要要求用户提供密码中的指定字符
- 使用适当的自动填充标记(
username、current-password、new-password、one-time-code) - 提供无需不受支持的信息转录或认知谜题的多重身份验证途径;账户恢复必须符合与登录相同的要求
- 如果使用 CAPTCHA 或认知测试,请依据 WCAG 3.3.8 评估,并提供适用的替代方案
<label for="username">Email address</label>
<input id="username" name="username" type="email" autocomplete="username">
<label for="password">Password</label>
<input id="password" name="password" type="password" autocomplete="current-password">
<button type="button" aria-controls="password" aria-pressed="false">
Show password
</button>
显示密码按钮必须一致地更新其可见标签和按下状态、保留焦点,且不得清除密码值。
高风险:将相关控件分组
使用 <fieldset> + <legend> 对相关控件进行分组。
缺少分组属于高风险问题——单选按钮组和复选框组如果没有组标签,就会变得难以理解。
<fieldset>
<legend>Notification preferences</legend>
<label><input type="checkbox" name="email-notify"> Email</label>
<label><input type="checkbox" name="sms-notify"> SMS</label>
</fieldset>
图例应简洁;不要仅为视觉样式而使用 <fieldset>。对于允许多选的复选框组,应说明用户可以选择多个选项。
严重:输入类型
根据值的含义,分别选择 type、autocomplete 和 inputmode。这样可以在移动设备上显示正确的虚拟键盘,并为辅助技术(AT)提供语义信息。
| 信息 | 推荐控件 |
|---|---|
| 电子邮件地址 | type="email" autocomplete="email" |
| 电话号码 | type="tel" autocomplete="tel" |
| 网站地址 | type="url" autocomplete="url" |
| 搜索查询 | type="search" |
| 当前密码 / 新密码 | type="password" autocomplete="current-password" / "new-password" |
| 一次性验证码 | 一个文本输入框,autocomplete="one-time-code" inputmode="numeric" |
| 具有递增 / 递减语义的数值 | type="number" |
| 外观像数字的标识符、邮政编码、卡号 | 使用带匹配的 inputmode / autocomplete 的 type="text" |
不要把所有数字都当作数值
仅当数值适合进行数学运算,且 min / max / step 有用时,才使用 type="number";绝不要用于标识符或可能带有前导零的值:
<label for="quantity">Quantity</label>
<input id="quantity" name="quantity" type="number" min="1" max="20" step="1">
<label for="postal-code">Postal code</label>
<input id="postal-code" name="postal-code" type="text" autocomplete="postal-code">
inputmode 用于指定虚拟键盘;它不会验证输入值。只有在生成的约束和错误消息适用于所有可接受值时,才添加 pattern;不要假设所有用户输入的都是 ASCII 数字。
日期输入
如果原生 <input type="date"> 符合产品的地区设置、浏览器和 AT 要求,就使用它;请测试实际实现。对于出生日期等日期,分开标注的文本输入框通常比原生日期选择器或自定义日历控件更易于理解和验证:
<fieldset>
<legend>Date of birth</legend>
<p id="dob-hint">For example, 23 4 1980.</p>
<label for="dob-day">Day</label>
<input id="dob-day" name="dob-day" inputmode="numeric"
autocomplete="bday-day" aria-describedby="dob-hint">
<label for="dob-month">Month</label>
<input id="dob-month" name="dob-month" inputmode="numeric" autocomplete="bday-month">
<label for="dob-year">Year</label>
<input id="dob-year" name="dob-year" inputmode="numeric" autocomplete="bday-year">
</fieldset>
除非用户需要基于日历进行选择,否则不要构建自定义日历对话框;如果确有需要,请实现并测试完整的对话框和网格键盘交互(参见 APG Date Picker 模式)。
<select> — 单选
原生 <select> 受到所有 AT 的良好支持。在没有合适默认值时,始终将空白 / 占位选项作为第一个 <option>。
多选
<select multiple> 的可发现性较差(Shift / Ctrl 点击),且不便于键盘操作。对于较短且固定的选项列表,优先使用 <fieldset> 中的复选框。<select multiple> 可能适用于面向专家的界面,但必须针对目标用户群进行可用性测试;如果使用,请添加可见说明(Hold Ctrl (or Cmd on Mac) to select multiple options.),并通过 aria-describedby 引用该说明。
<datalist>
为文本输入框提供自动完成建议;原生支持键盘访问,但播报质量不一,请使用你的 AT 测试矩阵进行测试。如果建议列表是唯一有效的值集合,它不能替代完全可访问的组合框;此时请改用 role="combobox" 和 APG Combobox 模式。
严重:个人数据的自动完成
个人数据字段缺少 autocomplete 属于严重问题,会直接影响依赖自动填充来避免重复输入的运动障碍和认知障碍用户。标签、name、type 和自动完成标记应描述相同的用途。
<input type="text" id="name" autocomplete="name">
<input type="email" id="email" autocomplete="email">
<input type="tel" id="phone" autocomplete="tel">
<textarea id="street" autocomplete="street-address"></textarea>
<input type="text" id="city" autocomplete="address-level2">
<input type="text" id="postal" autocomplete="postal-code">
测试自动填充时,不要假设 autocomplete="off" 会或应该禁用密码管理器和浏览器辅助功能。完整标记列表:
WCAG 1.3.5 输入用途。
严重:按钮和提交控件
- 每个按钮都必须有清晰说明其操作结果的名称;始终指定
type(表单内的<button>默认类型为submit) - 区分主要提交操作和次要操作;在实际可行时,避免使用“前往”或“继续”等含糊标签,改用更具体的标签
- 不要仅仅因为表单未填写完整就永久禁用提交按钮;用户必须能够发现验证错误并进行修正
- 防止重复提交,同时保留状态信息且不将焦点困住
严重:异步与状态反馈
- 日常进度和成功完成时,使用
aria-live="polite"/role="status";只有对于不能等待的紧急信息,才使用强提示 - 确保状态文本持续显示足够长的时间,以便用户阅读
- 如果提交后会跳转到新页面,请在新页面提供描述性页面标题和标题
- 除非当下确有必要,否则不要逐次播报每次按键、字符数变化或验证状态
异步失败未给出提示属于严重问题——屏幕阅读器用户无法得知操作是否已完成或失败。
严重:3.3.4 错误预防——法律、财务、数据
对于会产生法律承诺、金融交易、测试回答或用户控制的数据变更的表单,至少提供以下一项:
- 可撤销——可以撤销提交
- 已检查——检查数据是否有误,且用户可以更正
- 已确认——用户可以在最终提交前查看、确认并更正
<h2>Review your order</h2>
<dl>
<dt>Plan</dt><dd>Annual plan</dd>
<dt>Amount</dt><dd>$120.00</dd>
</dl>
<a href="/cart">Edit order</a>
<button type="submit">Confirm and pay $120.00</button>
财务/法律表单缺少错误预防属于严重问题;在金融服务、法律协议、医疗数据等受监管场景中,如果错误无法撤销,则可能升级为关键问题。
严重:重复输入(WCAG 3.3.7)
验证错误后,不要清除有效信息。在同一多步骤流程中,除非重新输入必不可少、出于安全要求或信息已失效,否则必须自动填入或提供选项,以便用户选择之前输入或提供的信息。例如:“账单地址与收货地址相同”选项;将账户标识符带入后续步骤;在结果页保留搜索查询。保留信息的同时保护个人信息——3.3.7 不要求在不同会话之间存储信息。
中等:说明
对于复杂的输入组,请在输入前提供简洁说明,并通过 aria-describedby 关联。此项为中等——大多数用户可以推断要求,但认知障碍用户会从预先说明中受益。
- 将说明放在输入项之前,而非之后
- 在相关时说明格式、单位、可接受的文件类型、限制和是否区分大小写
- 不要将必要说明仅放在占位文本或工具提示中
- 不要要求用户仅根据示例推断格式
- 确保用户在输入和查看信息时都能访问说明
中等:时间限制与会话超时
除非必不可少,否则避免设置时间限制(WCAG 2.2.1)。对于采用“提前警告并允许延长”机制的不活动超时:
- 在超时前发出警告;至少提供 20 秒时间,让用户通过简单操作延长会话;至少允许延长十次
- 说明数据是否会丢失;播报并显示警告
- 将焦点移入正确实现的模态对话框;关闭后将焦点返回之前的位置
<dialog id="timeout-dialog" aria-labelledby="timeout-title">
<h2 id="timeout-title">Your session will expire in 2 minutes</h2>
<p>Your unsaved information will be lost.</p>
<button type="button" id="extend-session">Stay signed in</button>
<button type="button" id="sign-out">Sign out</button>
</dialog>
在支持的情况下,使用 showModal() 打开原生 <dialog>——仅设置 aria-modal 并不会创建模态行为、管理焦点、使页面其余部分不可交互,也不会提供 Escape 键处理。对于信息类表单,会话超时属于中等问题;对于数据丢失后无法恢复的交易或法律提交,则属于关键问题。
中等:验证时机
- 至少在提交时进行验证
- 失焦时(离开字段时)进行行内验证是可以接受的,但必须明确限定在刚离开的字段——不要验证用户尚未访问的字段
- 避免在用户正在输入时进行干扰性的实时验证
中等:视觉布局与交互
- 确保控件、边框、说明、占位符、错误、焦点指示器和禁用状态符合文本与非文本对比度要求
- 不要仅使用颜色表示必填、无效、已选中、成功或警告状态
- 提供可见的焦点指示器;在 320px 视口宽度下重新排版,且无需水平滚动
- 支持文本间距覆盖设置,避免内容被裁切或重叠
- 为触摸和指针输入提供足够的目标尺寸与间距
- 不要让固定页眉、虚拟键盘或验证提示层遮挡获得焦点的字段
- 除非已告知用户相关行为,否则不要仅因控件获得焦点或值发生变化而改变上下文
测试要求
- **键盘:**仅使用键盘完成并提交表单;按照每个自定义控件文档中的操作方式使用控件;确认焦点顺序符合逻辑;触发错误并访问错误摘要中的每个链接;确认模态警告会限制焦点范围,并在关闭后将焦点移回原处;测试复制/粘贴/撤销/重做/密码管理器填入
- **屏幕阅读器/语音输入:**确认每个控件的名称、角色、状态、值、提示和错误均易于理解;必填/无效状态会被播报;分组控件会包含共用的问题;状态更新只播报一次且保持可见;可见标签包含在无障碍名称中
- **放大/重新排版/触摸:**200%/400% 缩放;320px 视口宽度;文本间距覆盖设置;触摸目标和屏幕键盘;浏览器自动填充
- **验证/恢复:**提交空表单以及部分/全部无效的表单;按不同于错误摘要顺序的顺序更正错误;确认有效值会保留;测试服务器端错误、网络错误、会话过期和重复提交
- **身份验证:**使用自动填充/密码管理器完成登录;粘贴完整密码和一次性验证码;测试每条 MFA/恢复流程;确认先前输入的信息在后续步骤中会保留
自动化检查可以发现缺失的名称、无效的 ARIA、对比度问题和部分状态问题,但无法判断说明是否易于理解、错误是否有用或整个流程是否易于使用。应包含 HTML 验证、无障碍树/无障碍名称断言、axe-core、自定义控件的键盘交互测试、焦点定位测试,以及身份验证字段的粘贴测试。除了客户端验证,还要测试服务器渲染的错误。
完成标准检查清单
- 所有控件都通过程序与
<label>关联 - 不使用仅含占位符的标签
- 在原生输入控件上使用
required;不冗余地添加aria-required - 必填状态通过文本传达(不单靠颜色)
- 对分组控件使用
<fieldset>/<legend> - 个人数据字段使用适当的
autocomplete值 - 不阻止粘贴和标准键盘操作
- 在可行的情况下,将
<select multiple>替换为复选框 - 仅在适用数学运算/步进器语义时使用
type="number" - 使用目标 AT 矩阵测试日期输入控件
- 使用 AT 测试
<datalist>;受限输入使用 APG Combobox 模式 - 无效字段设置
aria-invalid;更正后移除此属性 - 错误消息具体、可执行,并通过
aria-describedby关联 - 提供错误摘要,提交失败时将焦点移至摘要
- 向屏幕阅读器播报异步成功/失败状态
- 法律/财务/数据更改表单包含检查/更正/确认步骤(3.3.4)
- 多步表单避免重复输入(3.3.7)
- 身份验证支持粘贴和密码管理器,并避免认知谜题(3.3.8)
- 会话超时前发出警告,并使用无障碍原生
<dialog> - 不以颜色作为任何状态的唯一指示方式
- 键盘和屏幕阅读器操作检查均通过
关键 WCAG 标准
- 1.3.1 信息和关系(A)
- 1.3.5 识别输入目的(AA)——个人数据字段缺少此项时为严重问题
- 2.2.1 可调整计时(A)
- 3.3.1 错误识别(A)——缺少此项时为关键问题
- 3.3.2 标签或说明(A)——缺少此项时为关键问题
- 3.3.3 错误建议(AA)
- 3.3.4 错误预防——法律、财务、数据(AA)——缺少此项时为严重问题
- 3.3.7 重复输入(A)
- 3.3.8 无障碍身份验证最低要求(AA)
参考资料
- 完整最佳实践指南
- WAI 表单教程
- WAI-ARIA APG — 组合框模式
- WAI-ARIA APG — 日期选择器对话框示例
- WCAG 1.3.5 输入目的 — 完整的 autocomplete 令牌列表
- 理解 3.3.4 错误预防
- 理解 3.3.7 重复输入
- 理解 3.3.8 无障碍身份验证
**标准展望:**这些规则以 WCAG 2.2 AA 为目标。WCAG 3.0 仍在 制定中;其拟议的 APCA 对比度模型可能会影响错误状态的颜色 选择,但核心的标签、分组和错误要求预计会继续沿用。 关注:https://www.w3.org/TR/wcag-3.0/