大多数输入有一个共同点——它们最喜欢有一个伴侣标签! 而且幸福不止于此。 带有适当输入和标签的表单更容易让人们使用,这也会让人们感到快乐。
在这篇文章中,我想重点关注一些情况,即缺乏语义标签和输入组合会让各种人难以完成表单。 由于数百万人的生计依赖于表单,让我们深入了解 **我知道的最佳技巧**,以建立输入和标签之间充满活力和和谐的关系。
**内容警告:** 这篇文章涉及爱情和人际关系主题。
爱情故事从这里开始! 让我们介绍创建快乐标签和输入的基础知识。
如何配对标签和输入
有 **两种方法** 可以配对标签和输入。 一种是将输入包装在标签中(隐式),另一种是将 for
属性添加到标签并添加 id
到输入(显式)。
将隐式标签视为 **拥抱** 输入,将显式标签视为站在输入旁边 **握住** 它的手。
<label>
Name:
<input type="text" name="name" />
</label>
显式标签的 for
属性值必须与其输入的 id
属性值匹配。 例如,如果 for
的值为 name
,则 id
也应该具有 name
的值。
<label for="name">Name: </label>
<input type="text" id="name" name="name" />
不幸的是,即使使用了 for
和 id
属性,隐式标签也不被所有辅助技术正确处理。 **因此,始终最好** **使用显式标签而不是隐式标签。**
<!-- IMPLICIT LABEL (not recommended for use) - the label wraps the input. -->
<label>
Name:
<input type="text" name="name" />
</label>
<!-- EXPLICIT LABEL (recommended for use) - the label is connected to an input via "for" and "id" -->
<label for="explicit-label-name">Name: </label>
<input type="text" id="explicit-label-name" name="name" />
每个单独的输入元素应该只与一个标签配对。 标签也应该只与一个输入配对。 是的,输入和标签是一夫一妻制。 ♥️
**注意:** 此规则有一点例外:当我们处理一组输入时,比如多个单选按钮或复选框。 在这些情况下,使用 <legend>
元素对某些输入元素(例如单选按钮)进行分组,并用作整个组的可访问标签。
并非所有输入都需要标签
具有 type="submit"
或 type="button"
的输入不需要标签——value
属性充当可访问标签文本。 具有 type="hidden"
的输入在没有标签的情况下也可以正常工作。 但所有其他输入(包括 <textarea>
和 <select>
元素)都最适合有一个伴侣标签。
标签中包含什么
标签内部的内容应
- **描述其伴侣输入。** 标签想要向所有人展示它与它的输入伴侣属于在一起。
- **可见。** 可以单击或点击标签以将焦点设置到其输入上。 它提供的用于与输入交互的额外空间是有益的,因为它增加了点击或点击的目标。 我们稍后将更详细地介绍这一点。
- **仅包含纯文本。** 不要添加标题或链接等元素。 同样,我们将在下面进一步介绍“为什么”。
标签中内容的一个有用之处是可以添加格式提示。 例如,<input type="date" id="date">
的标签将是 <label for="date">
,正如我们所期望的那样。 但然后我们可以在标签和输入之间提供一个提示,提示用户日期需要以特定格式输入,例如 DD-MM-YYYY
,该提示的形式是一个 <span>
,用于指定该要求。 提示不仅指定日期格式,而且具有与输入上的 aria-describedby
属性相对应的 id
值。
<!-- Describes what the input is for - should be plain text only -->
<label for="date">Start date</label>
<!-- Describes additional information, usually about formatting -->
<span id="date-format">(DD-MM-YYYY):</span>
<input type="date" id="date" aria-describedby="date-format" min="2021-03-01" max="2031-01-01" />
这样,我们就可以获得清晰标签的益处,该标签描述了输入的用途,以及对用户输入需要以特定格式输入的额外提示。
建立健康关系的最佳实践
以下提示超越了基本知识,解释了如何确保标签和输入尽可能地快乐。
应该:在正确的位置添加标签
有一个 WCAG 成功标准指出 页面的视觉顺序应遵循元素在 DOM 中出现的顺序。 这是因为
使用屏幕放大镜和屏幕阅读器的低视力用户可能会感到困惑,因为阅读顺序似乎在屏幕上跳来跳去。 当源顺序与视觉顺序不匹配时,键盘用户可能难以预测焦点将转到哪里。
考虑一下。 如果我们有一些标准的 HTML,其中标签出现在输入之前
<label for="orange">Orange</label>
<input type="checkbox" id="orange" name="orange">
这会将标签放在 DOM 中输入之前。 但现在假设我们的标签和表单位于一个灵活的容器中,我们使用 CSS order
将其反转,这样输入在视觉上出现在标签之前
label { order: 2; }
input { order: 1; }
屏幕阅读器用户(在元素之间导航)可能希望输入在标签之前获得焦点,因为输入在视觉上首先出现。 但实际上发生的是标签获得了焦点。 请参阅 使用屏幕阅读器和键盘导航之间的区别。
因此,我们应该注意这一点。 通常将标签放置在复选框和单选按钮的输入右侧。 这可以通过将标签放置在 HTML 中输入之后来完成,确保 DOM 和视觉顺序匹配。
<form>
<!-- Checkbox with label on the right -->
<span>
<input type="checkbox" id="orange" name="orange">
<label for="orange">Orange</label>
</span>
<!-- Radio button with label on the right -->
<span>
<input type="radio" id="banana" name="banana">
<label for="banana">Banana</label>
</span>
<!-- Text input with label on the left -->
<span>
<label for="apple">How do you like them apples?</label>
<input type="text" id="apple" name="apple">
</span>
</form>
应该:使用屏幕阅读器检查输入
无论输入是从头开始编写还是使用库生成的,使用屏幕阅读器检查您的工作都是一个好主意。 这样做是为了确保
- 所有相关属性都存在——尤其是
for
和id
属性的匹配值。 - DOM 与视觉顺序匹配。
- 标签文本听起来清晰。 例如,“dd-mm-yyyy” 与其大写等效项(DD-MM-YYYY)的读法不同。
在过去几年中,我一直在使用 JavaScript 库(例如 downshift)来构建复杂的形式元素,例如自动完成或 组合框,它们建立在原生 HTML 元素(例如输入或选择)的基础上。 大多数库通过使用 JavaScript 添加 ARIA 属性来使这些复杂元素可访问。
但是,如果 JavaScript 出现故障或被禁用,使用 JavaScript 增强过的原生 HTML 元素的优势将完全消失,使它们无法访问。 因此,请检查这一点,并提供一个服务器端渲染的无 JavaScript 替代方案作为安全回退。
请查看这些 基本表单测试,以确定不同屏幕阅读器应如何编写和宣布输入及其伴侣标签或图例。
应该:使标签可见
连接标签和输入很重要,但保持标签可见同样重要。 单击或点击可见标签会将焦点设置到其输入伴侣上。 这是原生 HTML 行为,对大量用户有利。
想象一个标签想要自豪地展示它与输入的关联
也就是说,在某些情况下,设计需要隐藏标签。 因此,如果标签必须隐藏,那么以可访问的方式隐藏它至关重要。 一个常见的错误是使用 display: none
或 visibility: hidden
来隐藏标签。 这些 CSS 显示属性会完全隐藏元素——不仅在视觉上,而且在屏幕阅读器中也是如此。
考虑使用以下代码来视觉上隐藏标签
/* For non-natively-focusable elements. For natively focusable elements */
/* Use .visually-hidden:not(:focus):not(:active) */
.visually-hidden {
border-width: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
white-space: nowrap !important;
width: 1px !important;
}
Kitty Giraudel 深入解释了如何负责任地隐藏内容。
要避免的事项
为了维护输入和标签之间的良好关系,在将它们配对时,有一些事情是不应该做的。让我们深入了解这些事项以及如何避免它们。
不要:期望你的输入在所有浏览器中都相同
在一些较老的桌面浏览器中,某些类型的输入是不支持的。例如,type="date"
的输入在 Internet Explorer (IE) 11 中不受支持,甚至在 Safari 141(发布于 2020 年 9 月)中也不支持。这种输入会回退到 type="text"
。如果日期输入没有明确的标签,并且它在较老的浏览器中自动回退到文本输入,用户可能会感到困惑。
不要:用占位符代替标签
以下解释了为什么输入上的 placeholder
属性不应该代替标签
- 并非所有屏幕阅读器都会宣布占位符。
placeholder
的值在较小的设备上或在浏览器中翻译页面时,有被截断的风险。相比之下,标签的文本内容可以很容易地换行到新行。- 仅仅因为开发者可以在他们的大型视网膜屏幕上,在光线充足的房间里,在没有干扰的环境中看到浅灰色的
placeholder
文本,并不意味着每个人都能看到。placeholder
甚至可以使视力良好的人眯起眼睛,最终放弃填写表单。
- 一旦在输入中输入字符,其
placeholder
就会变得不可见,无论是视觉上还是对屏幕阅读器而言。如果用户需要回溯查看他们在表单中输入的信息,他们需要删除已输入的内容才能再次看到占位符。 placeholder
属性在 IE 9 及以下版本中不受支持,并且在 IE 11 中输入获得焦点时会消失。另外需要注意的是,在 IE 11 中无法使用 CSS 自定义占位符颜色。
占位符就像那个在一切都完美时出现,但在你需要它们时就消失的朋友。与其使用占位符,不如将输入与一个漂亮的、高对比度的标签配对。标签不会像占位符那样不稳定,并且始终对输入忠诚。
Nielsen Norman Group 有一篇深入的文章解释了为什么表单字段中的占位符是有害的。
不要:用其他属性或元素代替标签
当没有标签时,一些屏幕阅读器会查找相邻的文本并宣布它。这是一种随机的方法,因为屏幕阅读器可能找不到任何文本来宣布。
以下代码示例来自一个真实的网站。标签已经被一个<span>
元素所代替,该元素在语义上与输入无关。
<div>
<span>Card number</span>
<div>
<input type="text" value="" id="cardNumber" name="cardNumber" maxlength="40">
</div>
</div>
以上代码应该被重写以确保无障碍性,方法是**用一个for="cardNumber"
标签替换 span**。这是迄今为止最简单、最强大的解决方案,它能使大多数人受益。
虽然可以使用一个带有id
属性的 span 来代替标签,该id
属性的值与输入的aria-labelledby
属性匹配,但用户无法像使用标签那样单击 span 来聚焦输入。最好是**利用原生 HTML 元素的力量**,而不是重新发明它们。原生输入和标签元素之间的爱情故事不需要重写!它本身就很棒。
不要:在标签中放置交互式元素
标签中只能包含纯文本。避免插入标题或交互式元素,例如链接。并非所有屏幕阅读器都能正确宣布包含纯文本以外内容的标签。此外,如果用户想通过单击标签来聚焦输入,但标签包含一个链接,他们可能会错误地单击链接。
<form>
<div>
<!-- Don't do this -->
<input type="checkbox" id="t-and-c" name="name" />
<label for="t-and-c">I accept the <a href="https://link.com">terms and conditions</a></label>
</div>
<div>
<!-- Try this -->
<input type="checkbox" id="t-and-c2" name="name" />
<label for="t-and-c2">I accept the terms and conditions.</label>
<span>Read <a href="https://link.com">terms and conditions</a></span>
</div>
</form>
现实生活中的例子
我总是发现现实生活中的例子能帮助我更好地理解某些事物。我在网上搜索,找到了一个流行的组件库和网站上关于标签和输入的例子。下面,我将解释这些元素的不足之处,以及如何改进它们以确保它们更好地配对。
组件库:Material
MaterialUI 是一个基于 Google 设计系统的 React 组件库。它包含一个文本输入组件,它具有一个浮动标签模式,该模式已成为许多设计师和开发者的首选方案。
单击输入感觉很流畅,看起来也很棒。但问题就在这里。它的优势大多是表面的。
在撰写本文时,我发现该组件的一些问题包括
- 没有选项将标签置于输入之外,以提供更大的交互区域来聚焦输入。
- 有一个选项可以添加提示,就像我们之前看到的那样。不幸的是,提示仅通过接近度与输入相关联,而不是通过匹配的
id
和aria-describedby
。这意味着并非所有屏幕阅读器都能将帮助信息与输入关联起来。 - 标签在 DOM 中位于输入之后,导致视觉顺序不正确。
- 空的输入看起来像已经填写了内容,至少在它未处于活动状态时是如此。
- 单击输入时,标签会向上滑动,这使得它不适合那些希望减少运动的人。
Adam Silver 也解释了为什么浮动标签是有问题的,并对Material 的文本输入设计进行了详细的批评。
网站:Huffpost
Huffpost 网站 有包含新闻简报订阅表单的文章。
在撰写本文时,Huffpost 使用的电子邮件输入可以从以下几个方面进行改进。
- 缺少标签意味着更小的点击或轻触目标。输入上没有标签,而是有一个
aria-label
属性。 placeholder
和输入值的字体大小只有 11px,可能难以阅读。- 如果没有 JavaScript,整个输入会消失,这意味着如果 JavaScript 被禁用或损坏,用户将无法订阅新闻简报。
结束语
令人惊讶的是,许多人难以在结构不良的输入框中输入信息。这些人包括认知、运动和身体残疾人士,自闭症谱系障碍患者,脑损伤患者以及视力障碍者。其他难以输入信息的人还包括那些匆忙的人、网络连接不好的人、使用小型设备的人、使用旧设备的人以及不熟悉数字表格的人,等等。
此外,还有许多原因会导致 JavaScript 崩溃或在浏览器中被关闭,这意味着输入框会变得无法使用或完全无法访问。还有一些人能够完全查看网页,但他们可能选择使用键盘和屏幕阅读器。
我想传达的信息是,快乐的标签和输入框配对至关重要。如果你的表单无法使用,那么它无论多么美观都没有意义。我敢打赌,几乎每个人都愿意填写一个丑陋但易于使用的表单,而不是一个漂亮但会造成问题的表单。
感谢
我要衷心感谢以下人士对本文的帮助:Eric Eggert、Adam Silver、Dion Dajka以及Kitty Giraudel。他们合在一起的无障碍知识是不可阻挡的力!
脚注
- 1 实际上,日期选择器在 iOS 14 中得到了很好的支持,并且非常棒。可以想象,macOS 版本即将发布。 ⮑
文章开头说始终要明确标签。如果你这样做呢?这样在标记方面是否会提供最佳可读性?或者屏幕阅读器不喜欢这种方式?
事实是,隐式标签无障碍性的质量存在争议,不同的无障碍专家有不同的看法。我在很多地方都发现有人声称显式标签是最好的。例如Eric Eggert 关于为控件添加标签的文章。
关于前面关于
input
和label
的源代码顺序的观点,我认为label
不能被聚焦…有点像内向的男生和外向的女生… ;) 因此,当使用键盘在文档中进行 Tab 键操作时,键盘用户永远不会聚焦到label
上,无论它是否在关联的input
之前或之后。没错!标签不能通过常规的 Tab 键导航进行聚焦,但屏幕阅读器用户可以。请参阅 Leonie Watson 关于屏幕阅读器和键盘焦点之间的区别的帖子,这是一个很好的概述。
很棒的文章,Amber。我有一个简单的问题。
屏幕阅读器在这里究竟会宣布什么?
在我的“不要将交互式元素放在标签内部”Codepen 示例中,VoiceOver 会为包含链接的标签的输入框读出“我接受这些内容以及另外 1 个项目”。
这只是一个例子,结果可能会因屏幕阅读器而异。不幸的是,我无法使用所有屏幕阅读器进行测试。
有史以来最好的可视化效果。这让我的一天都变得愉快,Amber。
谢谢,Skythe!
开始日期 (DD-MM-YYYY)
不要这样做。这意味着,如果你点击“开始日期”,它会聚焦该字段,但如果你点击日期格式文本,它不会聚焦。这是毫无道理的混乱。将所有内容都放在标签中。
解释很棒,而且我喜欢这些卡通!
谢谢,Dom!
据我所知,Dragon 是唯一无法处理围绕字段的标签的 AT。假设我们不会回到 IE5 的 bug(或者 IE6?或者 IE4?)。
Eric Wright 已经介绍过这个问题(并展示了它有多令人沮丧),虽然他 2019 年演讲的幻灯片没有在线上,但我得到了包含相关注释的照片。
否则,Windows 和 macOS 的原生语音控制似乎并不介意。
仍然是一个避免它的理由,但了解问题的整体影响范围也很有意义。
我希望有一种方法可以在 CSS 中定位输入框的标签。
这不太符合这篇文章的意图,但值得一提的是
name
属性很重要。正如 MDN 所述,它“…用于服务器在表单提交时识别字段”。不幸的是,即使使用 for 和 id 属性,隐式标签也并非所有辅助技术都能正确处理。因此,始终使用显式标签而不是隐式标签是最好的方法。
这是否包括在点击标签时不聚焦输入框?
与其使用 (DD-MM-YYYY),不如使用“数字日-月-年。例如:12-02-2021”,这样更具描述性,而不是假设每个人都知道 DD-MM-YYYY 的含义。
您好,我正在学习如何编写 HTML、CSS 和 Javascript。我来到这里的原因是想要学习如何在网页上将标签和输入框居中,并在它们上方放一个 img 图片。我喜欢在所有元素周围添加边框作为视觉参考。但我不知道很多技巧。您能推荐一个学习 CSS 的好网站吗?
嗨,Danny!我们有一份很棒的(如果可以这么说)使用 CSS 将事物居中的指南,您可能想查看一下。:)
您好。感谢您发表这篇文章。我一直苦苦挣扎的一个问题是如何为一系列复选框提供一个合适的标题,使其在样式和功能方面都与其他字段的标签相匹配,我想知道您是否能提供帮助。
假设我有一个比萨订购表单,其中有一系列问题。大多数问题都是类型字段,带有描述要输入的信息的标签,例如:名字、姓氏等等。假设其中一个问题,比如配料,要求用户从一系列复选框中选择一个(或多个)选项,例如:帕尔马干酪、菠萝、香肠等等。到目前为止一切都很好。
但我想要的是为整个复选框系列提供一个标题,即:“配料”。在视觉上,这个标题/组标签应该与其他输入字段标签的样式和粗细一致,并为屏幕阅读器提供相同的功能。
传统观念认为,应该将复选框分组到一个 fieldset 中,并添加一个值为“toppings”的 legend,但 legend 通常以更大的字体大小显示,这使得这个“标题”显得过重。 toppings 问题与姓氏、名字等问题同等重要,因此 toppings 问题的标题应与其他字段的标签具有相同的权重。
为了解决样式问题,我只是创建了一个 span 元素,并使用 CSS 来匹配其他字段标签的样式。我需要知道的是,如何为屏幕阅读器提供一个功能性的关联,将这个 span 元素与它所引入的每个单独标记的 toppings 复选框关联起来。
最初,我认为你建议的“aria-labelledBy=”…”” 可以做到,但每个复选框已经有了自己的标签,所以我想不行。有什么想法吗?
嗨 John,你使用 fieldset 和 legend 的想法是正确的。如果你确保 legend 是 fieldset 的第一个子元素,你就无需使用额外的
aria-
属性来创建输入和 legend 之间的关联。然后你可以使用 CSS 来解决视觉权重问题。如果你由于某种原因无法使用
legend
和fieldset
(例如,因为你需要额外的包装元素或不同的结构),你可以通过将role="group"
分配给一个包装输入的div
,并使用aria-labelledby
来为它分配来自另一个元素的标签,来大致获得相同的语义。例如这将导致屏幕阅读器以与它宣布 fieldset 的 legend 相同的方式宣布“组标签”。
请注意,使用原生 HTML 元素可能会有更好的/更广泛的辅助技术支持。
今天我发现标签和控件的隐式关联还有另一个缺点 - 至少对于 Chrome/Edge 中的按钮来说,它会使整个标签区域可点击,而不是仅仅是可见的按钮。有一些解决方法,但我不会建议将按钮嵌套在标签中!