消灭没有名字的输入框
目标
编写一个注册表单,并确认每个输入框的可访问名称是否真的能被计算出来。这里没有浏览器,但名称计算只凭标记就只有唯一的答案。
为什么重要
“有没有写 label”可以用眼睛数出来,但这样抓不到 for 与 id 对不上的输入框。机器看的不是文字,而是计算结果,而这个计算有既定的顺序——aria-labelledby → aria-label → label → title → placeholder。
前面的一步给出了值,后面的就不再看了。所以仅仅一个 aria-label 就会把可见的 label 整个覆盖掉,屏幕上写的文字与语音就会分道扬镳。用语音操作的用户会念出看到的文字,因此在那一刻就无法操作了。
要创建的内容
只有一个文件:/root/work/forms/signup.html。既不需要 CSS,也不需要 JavaScript——本实验关注的是关联是否成立。
计算器
cd /root/work/forms
python3 /opt/lab/checks/html-form-lab/accname.py signup.html
它会显示每个输入框的名称,以及该名称来自哪里。断开的 aria-labelledby 和 aria-describedby 也会一并输出。
步骤
- 文档骨架、
form与提交按钮 - 三个输入框,让名称来自
label - 单选按钮分组,
fieldset与legend - 用
aria-describedby提供规则说明 - 错误状态——
aria-invalid与role="alert" type与autocomplete- 必填标记——既让眼睛看得到,也让程序读得到
- 把计算器的结果保存为
08-names.txt - 总结 →
09-notes.md
参考
- 表单实际上不必提交到任何地方。只检查标记。
- 如果
id重复,所有关联都只会指向第一个元素。评分器会先拦下这种情况。 - 自动检查只能发现问题的一部分。其余的问题,把鼠标移开,只用 Tab 键把表单填完,大多就会暴露出来。
搭起一套表单
创建 /root/work/forms/signup.html。其中必须有 <!doctype html>、<html lang="ko">、<title>、<meta charset>、<meta name="viewport">,并且在带有 action 和 method 的 <form> 中,必须有一个输入框和一个提交用的 <button>。
mkdir -p /root/work/forms。写上 action 和 method,即使 JavaScript 失效,表单也能提交——这是表单的默认行为。请用 button 来提交。input type="submit" 也可以,但按钮里无法放入图标或其他元素。
名称来自哪里
把输入框增加到三个以上,并让所有输入框的名称都来自 label。计算器输出的 출처=(韩文,意为“来源”)在三个输入框上都必须是 label。如果用 placeholder 或 title 来凑名称,就会失败。
label 的 for 与输入框的 id 一个字符也不能不同。用眼睛看它们紧挨在一起,对机器来说却毫无关系。请先用 python3 /opt/lab/checks/html-form-lab/accname.py signup.html 看一下现在的名称来自哪里。
分组有分组的名称
创建两个以上 name 相同的单选按钮,把它们放进同一个 <fieldset> 中,并用 <legend> 给出分组名称。每个单选按钮也必须有自己的 label。
单选按钮是多个合在一起构成一个问题。即使每个选项都有名称,“正在选择什么”也哪里都没有——这个位置由 legend 来填补。name 必须相同,它们才会互相取消选中。
规则是说明,而不是名称
把密码规则说明写成单独的元素,并用 aria-describedby 关联起来。说明文字必须在 10 个字符以上,而且不能与名称是同一句话。
如果把规则塞进 label,输入框的名称就会变成“密码至少十二个字符,包含数字和符号……”。名称必须简短,才能在列表中挑选。较长的说明请拆分成说明文字。
让程序能读取错误
给邮箱输入框加上 aria-invalid="true",并在 aria-describedby 中用空格列出帮助说明和错误消息这两个元素。在错误消息元素上加 role="alert"。
红色边框对分辨不出颜色的人毫无意义。aria-describedby 可以接受多个 id——请同时指向两者,这样即使出现错误,规则说明也不会消失。后来才出现的文字,必须有 role="alert" 才会被读出。
打字的次数也是可访问性
把输入文字的输入框增加到四个(请添加联系方式输入框),并给所有输入框设置标准的 autocomplete 值。邮箱输入框用 type="email" 和 autocomplete="email",密码用 new-password。
HTML 标准的 autofill 字段名称列表中没有的值,浏览器会直接忽略——e-mail 什么作用也没有。注册用 new-password,登录用 current-password。只有做出这种区分,密码管理器才会建议新密码。
必填也要让眼睛看得到
给两个以上的输入框加上 required,并在这些输入框的 label 文字中也加上必填标记。至少要留下一个选填输入框,而且选填输入框的名称中不能有必填标记。
只用 aria-required 的话只是告知,浏览器阻止提交的功能不会启用。反过来只用 required 的话,眼睛就无法分辨哪个输入框是必填的。两者都需要。如果全部都设为必填,标记就什么也区分不了。
用计算器确认
运行 accname.py,把结果保存为 /root/work/forms/08-names.txt。保存的行数必须与当前文档中的控件数相同,并且不能出现 출처=placeholder(韩文,意为“来源=placeholder”)或断开引用的警告。
python3 /opt/lab/checks/html-form-lab/accname.py signup.html | tee 08-names.txt。如果修改了文档,就必须重新保存——评分器会把保存的文件与当前文档进行比对。
什么是关联,什么是文字
在 /root/work/forms/09-notes.md 中写三行以上(120 个字符以上)。正文中必须包含 placeholder、fieldset、이름(韩文,意为“名称”)。文档本身仍然必须通过第 2 步的标准。
核心只有一点——关联不是文字,而是计算。 用自己的话写下哪些失误会造成“标记看起来完好,名称却不存在”的状态,下次手就会记住。