+
屏幕阅读器只把legend识别为该组控件的可访问名称,而h3只是普通文本。比如用户听到“步骤2:答题区域”,这个语义只有fieldset + legend能提供。div + h3组合在Lighthouse里直接报错:“fieldset缺少legend”。
常见错误包括:legend为空、只放图标、或用display: none隐藏。视觉上不想显示?用position: absolute; clip: rect(1px, 1px, 1px, 1px);——这样它还在可访问树里,但不占视觉空间。
所有按钮(含“下一题”)必须放在fieldset内部,否则键盘Tab会跳过整步;每步切换时,记得给当前fieldset加aria-current="step",并手动把焦点移到第一个可聚焦字段。
单选题怎么绑定label又不写死HTML结构
别用一堆input[type="radio"] + label硬编码。用JS动态渲染,数据统一存在数组里:
const questions = [
{
id: 1,
text: "你更倾向于先想清楚再行动,还是边做边调整?",
options: [
{ value: "analytical", label: "先想清楚" },
{ value: "adaptive", label: "边做边调整" }
]
}
];
渲染时用for + id显式关联:
关键点:
- 每个选项
id必须唯一,且不含空格或特殊字符
-
name值统一为"q" + question.id,确保浏览器原生单选逻辑生效
- 禁用
placeholder替代label——它不提供持久标签,也不被读屏识别
提交按钮和required校验怎么不误伤隐藏题目
浏览器的form.checkValidity()会扫描整个form里的required字段,不管它是否可见。第1步点“下一步”,第2步那些required字段就会导致校验失败。
解决方式只有两个,选一个坚持到底:
- 动态开关
required:切到第2步前,给[data-step="2"] [required]加required属性,其他步骤的全移除
- 不用
required,改用JS手动校验:只检查document.querySelector('[data-step="1"]').querySelectorAll('[required]')
中间步骤的按钮一律设type="button";仅最后“提交”按钮用type="submit",并在其click事件中不调preventDefault()——否则表单根本不会发出去。
动态更新结果页时屏幕阅读器为何没反应
AJAX加载结果、校验失败弹提示、跳转到解析页……这些变化若不主动通知,视障用户会卡在旧状态里,以为操作没响应。
错误消息必须用aria-live="polite"包裹,并放在DOM靠前位置(最好紧贴form开头)。例如:
模态结果页要同时设置:role="dialog"、aria-modal="true"、aria-labelledby指向标题元素。校验失败的字段,除了视觉高亮,必须加aria-invalid="true"和aria-describedby指向错误消息的id。
别用display: none隐藏错误消息——它会从可访问树中彻底移除内容。用visibility: hidden或opacity: 0配合aria-hidden="true"更稳妥。
最常被忽略的是焦点管理:结果页弹出后,焦点必须落到标题或第一个可操作元素上,否则键盘用户无法继续操作。