表单控件必须配,不能只靠视觉对齐;正确做法是用for和id显式绑定,每个input、select、textarea需有唯一id并被label引用,成组控件须用包裹,错误提示通过aria-describedby关联。

表单控件必须配 <label></label>,不能只靠视觉对齐
很多开发者用 CSS 把文字和输入框并排,却不写 <label></label>,结果屏幕阅读器根本读不出“邮箱”“密码”这些字段含义。浏览器也不会把点击文字自动聚焦到对应输入框——这不只是无障碍问题,连普通用户点错区域都填不了。
正确做法是用 for 和 id 显式绑定:
<label for="email">电子邮箱</label> <input type="email" id="email" name="email">
- 每个
<input>、<select></select>、<textarea></textarea>都得有唯一id,且被一个<label></label>引用 - 避免用
<label></label>包裹控件(嵌套写法),虽然合法但某些旧版辅助技术支持不稳定 - 按钮类控件如
<button></button>或<input type="submit">本身带可读文本,无需额外<label></label>
成组控件要用 <fieldset></fieldset> + <legend></legend>
单选按钮、复选框集合不是孤立字段,而是一个逻辑组。“性别”“兴趣爱好”这类选项必须用 <fieldset></fieldset> 包裹,并通过 <legend></legend> 声明组意图。否则屏幕阅读器会把每个选项单独播报,用户完全不知道它们属于同一主题。
示例:
-
<legend></legend>必须是<fieldset></fieldset>的第一个子元素,不可省略 - 不要用
<div> + CSS 模拟分组视觉效果,那对辅助技术毫无意义 <li>如果组内只有一个控件(比如单个开关),通常不需要 <code><fieldset></fieldset>,直接用<label></label>即可
错误提示和帮助文本要通过 aria-describedby 关联
表单验证失败时,光在输入框下方放一段红色文字远远不够。屏幕阅读器不会自动读它,键盘用户也看不到焦点跳转。必须用 aria-describedby 把错误消息或格式说明“挂”到对应控件上。
<label for="password">密码</label> <input type="password" id="password" name="password" aria-describedby="pw-hint pw-error"><p id="pw-hint">至少8位,含大小写字母和数字</p> <p id="pw-error" class="error">密码不符合要求</p>
-
aria-describedby的值是空格分隔的多个id,可同时关联帮助文本和错误提示 - 错误出现时,记得同步设置
aria-invalid="true",并确保id存在且唯一 - 不要用
title属性替代——它触发延迟、不可键盘访问、多数屏幕阅读器默认不读
<main></main> 和 <form></form> 的嵌套关系不能乱
表单是页面主要内容的一部分,不是独立文档。所以 <form></form> 应该放在 <main></main> 内部,而不是和 <main></main> 并列或包在 <section></section> 里再塞进 <main></main>。否则语义层级断裂,搜索引擎和辅助技术可能误判内容权重。
-
<main></main>必须且只能出现一次,且不能是<header></header>、<footer></footer>、<nav></nav>的后代 -
<form></form>可以出现在<main></main>、<article></article>或<section></section>中,取决于上下文——登录表单放<main></main>,评论表单放<article></article>更合理 - 别为了“结构好看”把整个表单包进
<section></section>却不加标题;<section></section>必须自带<h2></h2>–<h6></h6>,否则不如用<div> <p>语义标签不是贴标签游戏,关键在是否真实反映内容关系。一个没 <code><label></label>的表单,再漂亮的<header></header>和<footer></footer>也救不回来。











