TT Lab
开始
学习 学习路径 课程

HTML — 一个标签顶一项功能

消灭没有名字的输入框

在 TT Lab 中继续学习

目标

编写一个注册表单,并确认每个输入框的可访问名称是否真的能被计算出来。这里没有浏览器,但名称计算只凭标记就只有唯一的答案。

为什么重要

“有没有写 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 也会一并输出。

步骤

  1. 文档骨架、form 与提交按钮
  2. 三个输入框,让名称来自 label
  3. 单选按钮分组,fieldset 与 legend
  4. 用 aria-describedby 提供规则说明
  5. 错误状态——aria-invalid 与 role="alert"
  6. type 与 autocomplete
  7. 必填标记——既让眼睛看得到,也让程序读得到
  8. 把计算器的结果保存为 08-names.txt
  9. 总结 → 09-notes.md

参考

搭起一套表单

创建 /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 步的标准。

核心只有一点——关联不是文字,而是计算。 用自己的话写下哪些失误会造成“标记看起来完好,名称却不存在”的状态,下次手就会记住。