我应该将输入元素放在标签元素内吗?


605

是否存在关于嵌套HTML labelinputHTML元素的最佳实践?

经典方式:

<label for="myinput">My Text</label>
<input type="text" id="myinput" />

要么

<label for="myinput">My Text
   <input type="text" id="myinput" />
</label>

107
<input />放进的最大优点之一<label>是,您可以在示例中省略forid<label>My text <input /></label>。好多了!
Znarkus 2011年

16
虽然我同意input在语义上不属于a的内部label,但今天我注意到Bootstrap开发人员不同意我的看法。某些元素(例如,内联复选框)的样式不同,具体取决于元素的input内部还是外部。
Blazemonger

6
顺便说一句,创建这个想法真是个坏主意,<label for="id">因为我在页面上有多个表单,而且我不能id在没有陷入unique id per page陷阱的情况下对许多小部件使用属性。访问小部件的唯一可接受的方法是form + widget_name
MaxZoom

5
@MaxZoom,如果您的页面上有许多不同的表单,且具有相同的字段名称,以至于无法输入唯一的ID,您可能需要重新考虑一下页面设计,恕我直言;显然,我不知道您的情况,但是那对我来说很难闻
肯·贝洛斯

5
@kenbellows将两个Search表单放在一页上是设计师/企业(不是我)的想法。最佳的用户体验做法可能会随着时间而改变,但是HTML应该足够灵活(IMHO)才能涵盖任何可见的情况。
MaxZoom

Answers:


528

从w3开始:标签本身可以位于相关控件之前,之后或周围。

<label for="lastname">Last Name</label>
<input type="text" id="lastname" />

要么

<input type="text" id="lastname" />
<label for="lastname">Last Name</label>

要么

<label>
   <input type="text" name="lastname" />
   Last Name
</label>

请注意,当表格用于布局时,不能使用第三种技术,标签位于一个单元格中,而其关联的表单字段位于另一个单元格中。

任一有效。我喜欢使用第一个或第二个示例,因为它可以为您提供更多的样式控制。


14
答案是正确的,但按照我自己的实践,我通常会在此处给出由superUntitled给出的第一个示例,用于文本框,文本区域和选择。但是对于单选按钮和复选框,我通常使用第三个示例,在该示例中,我想在随附的文本之前输入内容,而不想要其余标签和字段所使用的固定宽度和/或浮动类型。因此,在任何给定的表单上,您可能会发现我同时使用了这两种格式。
Funka 2011年

6
我想知道是否<label for="inputbox"><input id="inputbox" type="text" /></label>按照他们的标准通过了。
马特

63
太糟糕了,您不能在输入标签内嵌套标签。如果从抽象的角度来看,标签实际上是输入的属性,那么它在语义上会更加合理。
Alex

9
链接的WCAG文档包括以下选项“控件包含在包含标签文本的标签元素中”。我不知道自@Sorcy发表评论以来的几年中是否添加了该标签,但是标签输入方案现在被认为是有效的。
Alex Weitzer 2014年

6
当您将click事件处理程序附加到标签时,至少在chrome中,标签内部的输入存在问题,单击该标签时,该处理程序将被触发两次。您可以return false;在处理程序的末尾使用,这是可以实现的,但是如果您可能还有其他需要随后执行的处理程序,并且无法停止传播,那么这将成为问题。
wired_in

67

我更喜欢

<label>
  Firstname
  <input name="firstname" />
</label>

<label>
  Lastname
  <input name="lastname" />
</label>

过度

<label for="firstname">Firstname</label>
<input name="firstname" id="firstname" />

<label for="lastname">Lastname</label>
<input name="lastname" id="lastname" />

主要是因为它使HTML更具可读性。而且我实际上认为我的第一个示例更易于使用CSS进行样式设置,因为CSS与嵌套元素非常兼容。

但这是我的口味问题。


如果需要更多样式选项,请添加一个span标签。

<label>
  <span>Firstname</span>
  <input name="firstname" />
</label>

<label>
  <span>Lastname</span>
  <input name="lastname" />
</label>

我认为代码看起来仍然更好。


3
在标签内包括输入与使用HTML进行布局相同。
埃米尔(Emil)

8
对于以下情况,我也喜欢此解决方案:(<label>Expires after <input name="exp" /> days</label>标签在输入元素之前和之后)
Philipp

我认为最后一个例子是-除了为和id属性-不是真的任何不必旁边输入标签不同,这两个包裹成一个divli或什么不是,是!?
retrovertigo

1
@retrovertigo-功能上?不。它只是减少标记,并减少术语的语义过度使用。我们知道输入firstname应遵循的标签firstname,但浏览器需要声明。这完全取决于您的口味,以及您认为代码中看起来(最好是最容易调试)的东西。我比较喜欢现在使用嵌套,尽管花了一段时间才习惯了。
Xhynk

3
@MPavlak-快速浏览,我从w3.org找到了此指南。w3.org/WAI/tutorials/forms/labels。然后,我检查了w3.org/TR/WCAG20-TECHS/H44.html。底部(模糊不清)说,要声明符合性,您需要通过测试标准,并特别声明您应使用for属性。实际上,当我上一次在Apple Voiceover中测试此功能时(台式机屏幕阅读器市场份额为10%,移动屏幕阅读器市场份额为60%),隐式标签不起作用,所以这是另一个主要因素。希望有帮助!
詹姆斯·韦斯特盖特

39

如果将输入标签包括在标签标签中,则无需使用'for'属性。

就是说,我不喜欢在标签中包含输入标签,因为我认为它们是独立的而不包含实体。


8
for需要您使用id,但这会使分层结构的布局变得非常困难:-(
lethalman 2013年

39

行为差异:在标签和输入之间的空白处单击

如果单击标签和输入之间的空格则仅当标签包含输入时,它才会激活输入。

这是有道理的,因为在这种情况下,空格只是标签的另一个字符。

<p>Inside:</p>

<label>
  <input type="checkbox" />
  |&lt;----- Label. Click between me and the checkbox.
</label>

<p>Outside:</p>

<input type="checkbox" id="check" />
<label for="check">|&lt;----- Label. Click between me and the checkbox.</label>

能够在标签和框之间单击表示它是:

  • 更容易点击
  • 不清楚开始和结束的地方

Bootstrap复选框v3.3示例使用内部输入:http : //getbootstrap.com/css/#forms明智的做法是遵循它们。但是他们在v4.0 https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios中改变了主意,所以我不知道什么是明智的了:

复选框和单选按钮的使用旨在支持基于HTML的表单验证并提供简洁,可访问的标签。因此,我们的<input>S和<label>s如相对于一个同级元素<input>内的<label>。由于您必须指定id并使属性与<input>和关联,所以这有点冗长<label>

UX问题详细讨论了这一点:https : //ux.stackexchange.com/questions/23552/should-the-space-between-the-checkbox-and-label-be-clickable


这不是规格差异。切换在所有兼容的浏览器中都适用。
hexalys 2014年

@hexalys感谢您的报告。我已经更新了答案。您是说兼容浏览器在两种情况下都应该切换还是不切换?如果您可以链接到相关的标准文章,那就太好了。
Ciro Santilli郝海东冠状病六四事件法轮功2014年

1
是。尽管我没注意到你的例子会误导人,因为你的空间并不是真正的文本空间。这是margin复选框中的一个。您的示例中的Firefox行为是特殊的,似乎是一个错误。A label将包含可单击的内联内容周围的空格或填充。但是,考虑到标签的内容模型是内联/ 短语内容,则输入的边距不应是可单击的,除非制作display: block了标签,在这种情况下,标签的内部block在所有浏览器中都可以单击。
hexalys 2014年

1
请注意,答案中的Bootstrap链接转到v3.3的文档。v4.0文档似乎表明他们已经改变了主意:“复选框和单选按钮的使用旨在支持基于HTML的表单验证并提供简洁,可访问的标签。因此,我们的<input> s和<label> s是同级元素,而不是<label>中的<input>。这有点冗长,因为您必须指定id并使属性关联<input>和<label>“。
迈克尔·克雷布斯

2
这种行为差异对我来说是一个很大的差异。当元素是同级元素时,两个元素上的任何边距都会减少可触发输入元素的可点击表面积。将输入内容嵌套在标签内可保留最大的可点击区域,即使对于那些需要精确的鼠标或触摸移动的用户也可提供最大的可访问性。在Bootstrap 4中,嵌套仍然可以工作,并且仍显示嵌套内容而无需调整或覆盖任何Bootstrap CSS。
Turgs

17

我个人喜欢将标签保留在外面,就像您的第二个示例一样。这就是为什么存在FOR属性的原因。原因是我经常将样式应用到标签上,例如宽度,以使表单看起来不错(下面的简写形式):

<style>
label {
  width: 120px;
  margin-right: 10px;
}
</style>

<label for="myinput">My Text</label>
<input type="text" id="myinput" /><br />
<label for="myinput2">My Text2</label>
<input type="text" id="myinput2" />

这样可以避免表格和表格中的所有垃圾。


3
您不应该将演示文稿留给CSS,而不是<br />用于分隔输入吗?
Znarkus 2011年

1
@Znarkus-是的,通常我将它们包装在OL / LI中以处理这样的格式,这只是一个简单的速记示例。
鹦鹉

1
@Parrots:imo在语义上没有多大意义。如果需要包装它们,为什么不只用标签包装它们呢?
Znarkus 2011年

1
@Parrots基于这种推理,我认为页面上的所有内容都应放在ul / li中。有了<label> <span>My text</span> <input /> </label>您所需的所有样式选项。
Znarkus

1
使用“ for”会强制您使用一个id,这对于分层布局是不利的。
lethalman

15

有关W3的建议,请参见http://www.w3.org/TR/html401/interact/forms.html#h-17.9

他们说这可以通过任何一种方式完成。他们将这两种方法描述为显式的(使用带有元素ID的“ for”)和隐式的(将元素嵌入标签中):

显式:

for属性将标签与另一个控件明确关联:for属性的值必须与关联控件元素的id属性的值相同。

隐式:

若要将标签与另一个控件隐式关联,则control元素必须位于LABEL元素的内容之内。在这种情况下,LABEL只能包含一个控制元素。


我只是发现隐式在IE中不起作用...。有什么想法吗?
carinlynchin

11

两者都是正确的,但是将输入置于标签内会使使用CSS样式时的灵活性大大降低。

首先,a <label>被限制在其中可以包含的元素中。例如,如果不在标签内,则只能<div><input>和文本之间放置一个。<input><label>

其次,虽然有一些变通方法可以使样式更容易,例如用间距将内部标签文本包裹起来,但是某些样式将从父元素继承而来,这会使样式更加复杂。


不够灵活?你能详细说明吗?正如其他人提到的那样,您可以简单地将内部标签文本用跨号包裹起来,除非这使它的灵活性降低了?
MPavlak '16

7

一个值得注意的“陷阱”指示您在一个带有显式“ for”属性的<label>元素内不应包含多个输入元素,例如:

<label for="child-input-1">
  <input type="radio" id="child-input-1"/>
  <span> Associate the following text with the selected radio button: </span>
  <input type="text" id="child-input-2"/>
</label>

尽管这对于自定义文本值仅次于单选按钮或复选框的表单功能而言很诱人,但label元素的单击焦点功能将立即将焦点移到ID在其“ for”属性中明确定义的元素,几乎使用户无法单击包含的文本字段来输入值。

就个人而言,我尽量避免使用带有输入子元素的标签元素。标签元素在语义上不适合包含比标签本身更多的内容。如果要在标签中嵌套输入以实现某种美感,则应改用CSS。


4
这不是“陷阱”。它显然是规范的一部分;标签中最多可以包含1个控件。您还将在此处混合使用隐式和显式样式-如果将控件放在标签内,则不需要for...如果要使用for,则将控件包含在标签内没有多大意义。
cHao 2011年

没错,但是似乎该规范并没有被很好地理解。我们在Drupal 6的Forms API中遇到了这个问题,该API生成的标记创建的场景与上述情况完全不同。我的同事和我挠头一两分钟,所以我想在这里解决这个问题,以避免将来出现潜在的混乱。
亚伦

在label-> input场景中不需要“ for”。每个标签一个输入,它的好处是不必知道名称或ID,并且您可以执行漂亮的CSS样式来封装内容,并在单击其中的任何其他元素时使焦点出现。请参阅zipstory.com/signup,以获取清洁方法的示例。
杰森·塞布林

谢谢; 这回答了我遇到的另一个相关问题,即标签内部是否可能有多个输入。(上下文:多个单选按钮选项,每行一个,每个单选按钮条目具有1、2、3或更多类型的文本输入,目的是单击具有选择该行的单选按钮结果的行,如果(未选中,并允许编辑该行上的输入/输入。)这为在表单中具有多个用于非输入文本的标签打开了大门,但是它回答了我关于我认为是否可以的问题。(不是。)
Christos Hayward

6

正如大多数人所说,这两种方法确实有效,但是我认为只有第一种方法应该可行。从语义上讲严格,标签不“包含”输入。我认为,标记结构中的包含(父/子)关系应反映视觉输出中的包含。也就是说,标记中围绕另一个元素的元素应在浏览器中围绕该元素绘制。因此,标签应该是输入的同级,而不是父级。因此,第二个选项是任意的并且令人困惑。每个阅读过Python Zen的人都可能会同意(扁平比嵌套更好,稀疏比密集更好,应该有一种-最好只有一种-显而易见的方式...)。

由于W3C和主要浏览器供应商的此类决定(允许“以您喜欢的方式”,而不是“以正确的方式”),今天的网络是如此混乱,我们开发人员必须应对以及各种各样的旧代码。


5

我通常会选择前两个选项。我已经看到了使用第三个选项时的情况,当嵌入标签和CSS的单选选项包含类似

label input {
    vertical-align: bottom;
}

为了确保收音机的正确垂直对齐。



2

我非常喜欢将元素包装在我的内部,<label>因为我不必生成ID。

我是一名Javascript开发人员,React或Angular用于生成可由我或其他人重用的组件。这样就很容易在页面中复制一个id,从而导致奇怪的行为。


1

您需要考虑的一件事是复选框和无线电输入与javascript的交互。

使用以下结构:

<label>
  <input onclick="controlCheckbox()" type="checkbox" checked="checkboxState" />
  <span>Label text</span>
</label>

当用户单击“标签文本”时,将触发一次controlCheckbox()函数。

但是,当单击输入标记时,在某些较旧的浏览器中,可能会触发controlCheckbox()函数两次。这是因为输入和标签标签都触发附加到复选框的onclick事件。

然后,您的checkboxState中可能会有一些错误。

我最近在IE11上遇到了这个问题。我不确定现代浏览器是否会遇到这种结构问题。


-1

放置input在内部的主要优点label是对人类的打字效率和对计算机的字节存储。

@Znarkus在对OP的评论中说,

<input />放进的最大优点之一<label>是,您可以在示例中省略forid<label>My text <input /></label>。好多了!

注意:在@Znarknus代码中,未包含在注释中未明确说明的另一种效率。type="text"也可以省略,input默认情况下将呈现文本框。

击键和字节[1]的并排比较。

31次击键,31个字节

<label>My Text<input /></label>

58次击键,58个字节

<label for="myinput">My Text</label><input id="myinput" />

否则,这些片段在视觉上是相等的,并且它们提供相同级别的用户可访问性。用户可以单击或点击标签以将光标放置在文本框中。

[1]在Windows的记事本中创建的文本文件(.txt),Windows File Explorer属性中的字节

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.