在HTML表单中最佳的布局方式是什么?

32

我想展示一个包含带标签的文本字段的HTML表单,就像这样:

      名字:  [_____________]
       姓氏:  [_____________]
   出生日期:  [________]

我的显而易见的方法是使用一个<TABLE>,然后将标签和文本字段放在其单元格中,但是否有更好的方法,例如基于CSS的方法?

编辑:

  1. 我正在寻找一种减少HTML文件冗余的方式。
  2. 是的,我正在寻找标签的自动大小调整。请参见关于标签换行的相关问题
9个回答

36
如果您需要标签在字段左侧,那么请使用表格。表格不仅可以在旧浏览器上很好地降级,而且它们会自动根据标签文本调整列宽(假设您在包含标签的单元格上使用white-space: no-wrap,并且/或者 - 这是真正的异端邪说 - 在th标签上使用可靠的nowrap属性),它们能够很好地处理被缩小的情况,并且它们很容易。将每个标签单元格设置为标题,将每个字段单元格设置为普通单元格。确保标签真的是

1
@doublep:并不是这个意思,但我理解你可能会这样理解。(不过没有必要骂人。)但为了明确起见:我不认为任何想要踩这个的人都是一个笨蛋。 - T.J. Crowder
9
@T.J.:这是一个原则问题。表格永远不应该用于布局。 - Josh K
2
+1 给我。CSS 推动的目的不是要摆脱所有的 <table/>,而是停止使用 <table/> 来呈现非表格布局。但如果你实际上正在呈现一个表格... 使用 <table/>!这是语义上正确的选择。 - roufamatic
3
@Josh: 你说得对,表格不应该用于布局。但是在表单中使用表格是完全语义化的,因为表单就是表格数据。另外,我想强调一点,“纯CSS”这个词让我感到非常恼火,因为从定义上来说,一个完全由CSS构建的网站是不存在的概念。 - DisgruntledGoat
5
@Josh: 不想拖延太久(尤其是因为我最初同意这不是表格的语义使用),但是Goat和roufamatic有一个有趣的观点。如果我有一系列行,其中th包含(比如说)“名字:”,接下来的td包含“Sam”,下一行的th是“姓氏:”,随后是td =“Samson”,那么这就是表格数据。那么如果“Sam”和“Samson”是字段,为什么它不是表格数据呢?这是一个有趣的问题...... - T.J. Crowder
显示剩余11条评论

19

就可用性而言,如果垂直空间不是限制因素,则每个字段上方都带有标签的字段列表是最快读取和填写的,并且可以美观地完成。有关更多信息,请参见网络上的许多可用性研究,例如 http://www.lukew.com/resources/articles/web_forms.html


我对LukeW的观点表示赞同,但是我希望将标签右对齐到左边,这是他的研究中为普通用户提倡的做法之一。 - Tony the Pony
+1 我非常喜欢这些东西,不仅仅是因为语义标记的原因,还因为它们看起来很美观。 - T.J. Crowder
4
感谢您提供的翻译机会。以下是翻译的结果:在一个我本来期望焦点落在表格布局战争上的问题上,引用“可用性研究”,我给出了+1。 - Richard JP Le Guen

14

我想使用定义列表(<dl>),因为它们通常是语义上正确的。标签由用户输入定义。对我来说有意义。<dl>比表格更准确地表达了语义内容。

<dl>
    <dt><label for="name>Name</label></dt>
    <dd><input type="text" id="name" /></dd>

    <dt><label for="email>Email</label></dt>
    <dd><input type="text" id="email" /></dd>
</dl>

这里有一个示例

顺便说一句,它们在所有浏览器中都能很好地降级,甚至包括文本浏览器。


这种技巧我从未想过...它似乎在语义上是正确的,简单的,并且实际上可以跨浏览器工作...在这三个类别中都成功了,这使它成为正确的答案,在我看来。+1 - rmeador
这是一个有趣的方法。我不认为我在语义上与你一致,但这只是个人观点问题。可悲的是,它仍然存在所有我知道的CSS解决方案都有的问题:标签不会自动调整大小,而OP说她想要这样做。您必须明确给出它们的大小(在您的“工作示例”中,为浏览器宽度的50%的33%)。 - T.J. Crowder
应用 display: inline-block 不就可以自动调整大小吗? - Boris Guéry
不,恐怕这并没有什么帮助。它大多数情况下看起来是有效的是width:33%,而不是display:inline-block(虽然你也需要在dt中使用它)。这意味着dt将至少占容器的33%,但长标签会更长,导致错开的外观。当您使标签如此大时(浏览器窗口宽度的~17%),可能并不是很重要,但通常您没有那么多的空间可用。 - T.J. Crowder
非常聪明的技巧 - Vitaliy Terziev

5

我认为我做的类似于这样,但也不会自动调整文本的长度,但在我看来更加简洁。

<form>
  <label for="firstName">First Name</label>
  <input type="textfield" name="firstName" />

  <label for="lastName">Last Name</label>
  <input type="textfield" name="lastName" />
</form>

label {
  float:left;
  width:30px;
}

input {
  float:left;
  margin-left:30px;
}

3
固定宽度指的是您的演示取决于内容。 - Matteo Riva
如果您为标签添加clear:both,并为labelinput都添加display:block,则此方法效果最佳。 - ccpizza

4

3

CSS表格显示

从IE8+开始,您可以使用CSS表格显示来实现此功能:

enter image description here

<!DOCTYPE html>
<html>
<head>
<style>
form > div > label { text-align: right; vertical-align: top }
form { display: table; }
form > div { display: table-row; }
form > div > label,
form > div > textarea,
form > div > input { display: table-cell; }
</style>
</head>
<body>
<form method="post">

<div>
<label for="name">Name</label>
<input type="text" id="name" size="14"/>
</div>

<div>
<label for="message">Message</label>
<textarea id="message"></textarea>
</div>

<div>
<label for="ssn">Social Security Number</label>
<input type="text" id="ssn"/>
</div>

<div>
<label></label>
<input type="submit" value="Send"/>
</div>

</form>
</body>
</html>

1
这看起来就像你正在使用表格... 是通过 CSS,但基本上是一样的... - Alexis Wilke

2
使用像Blueprint这样的CSS框架来为表单添加样式。
另一个技巧是使用CSS创建虚拟“列”,并将它们浮动在一起。标签在一列中,输入在另一列中。将两个列放在具有足够大宽度的div中,并将列浮动到您想要对齐的相反方向。
以下是一些代码(因为我正在创建一个表单),可以用于基本表单。唯一的限制是输入上的大右边距。
form input, form select
{
    float: right;
    margin-right: 650px;
}
form label
{
    float: right;
    margin-top: 5px;
    margin-right: 10px;
}
form .nofloat
{
    float: none;
    margin: 0;
}
form br
{
    clear: both;
}

并按如下布局

<input type="text" id="name" />
<label for="name">Name</label>
<br />

在这个小而狭窄的代码之上,还有一篇关于使用CSS创建无表格表单的完整文章


我上一次查看Blueprint(大约一年前)时,它在所有流行的浏览器上都无法正确渲染,并涉及过多的黑客和复杂操作。 - T.J. Crowder
4
相较于表格至少可以保持逻辑阅读顺序,两列对于可访问性来说更加糟糕。 - bobince
1
有人可以非常地争辩,它实际上是一张信息表。 - Matteo Riva
无论是输入还是输出,它都是数据。电子表格中有很多“输入”单元格,但它仍然是一个表格,不是吗? - Matteo Riva
3
很难反驳“不是这样”的论点,我也没什么好说的。 - Matteo Riva
显示剩余3条评论

0

表格的一个问题是空间错误。当您不使用表格时,可以像这样编写标签和输入:

<label for="foo">Blah <input id="foo" type="text"/></label>

适当地封装输入和标签。

另一方面,在表格中,您可以将它们分开:

<td><label for="foo">Blah</label></td><td><input id="foo" type="text"/></td>

这意味着</label>和<input/>之间的区域不响应鼠标点击。

对于普通字段来说还好,但对于单选按钮和复选框来说真的很烦人(或者可能只是我太挑剔了)。

现在,回答你的问题:我认为没有一种好的方法可以在CSS中格式化列(除非列宽已知--你可以用JavaScript实现这个功能...)。所以T.J. Crowder肯定有一个很好的答案。

然而,CSS(和强制宽度)有一个优点,就是我曾经创建过一个非常大的表单,覆盖整个屏幕。所有字段都会出现在一个屏幕上(因为客户想要这样),而CMS没有输出表格。但即使如此,表格也将是一场噩梦,因为所有字段都被放置在不对齐的列中。这在表格中将会非常困难(使用表格作为网格,这将是一个布局表格!)。


更新:

根据下面的评论,singe31表示<input/>不能定义在<label>标签内。这是错误的。HTML 4.01 DTD很容易阅读,我们可以看到:

<!ELEMENT LABEL - - (%inline;)* -(LABEL) -- form field label text -->
<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">

换句话说,一个 <input/> 可以出现在 <label> 标签中,这是完全合法的。
HTML 5 在 w3c 的文档中明确表明这是合法的。

http://www.w3.org/html/wg/drafts/html/master/forms.html#the-label-element

向下滚动一点,直到看到“代码示例”:

代码示例

例如,在点击或按下复选框标签会选中复选框的平台上,单击或按下以下代码片段中的标签可能会触发用户代理运行合成点击激活步骤来激活输入元素,就好像元素本身已被用户触发:

<label><input type=checkbox name=lost> 丢失</label>

在其他平台上,行为可能仅是将控件聚焦或不执行任何操作。


<input> 应该不应该一开始就在 <label> 里面。它要么在前面,要么在后面,绝不能在里面。 - singe3

0

通常情况下,我发现如果不使用表格来创建表单,就会出现一些问题。以下是我无法解决的一般问题:

  • 没有真正的背景颜色可以为字段/输入设置背景颜色
  • 自动调整列宽,但我认为这没关系
  • 使用CSS进行字段悬停,你可以使用JS,但表格可以使用纯CSS实现

可能还有一些我忽略的问题,但如果您使用CSS,则最灵活的标记如下:

<div class='form-field'>
   <label>Name</label>
   <input />
</div>

如果您想在标签部分使用多个字段,则会出现问题,因此您必须引入另一个div来容纳输入(以允许标签仍然向左浮动等):
<div class='form-field'>
   <label>Name</label>

   <div class='form-inputs'>
      <input />
      <input />
   </div>
</div>

通过上述标记,您可以实现非常灵活的表单,我不会发布CSS,因为它与2列布局非常相似。

我仍然需要坐下来尝试并弄清楚纯CSS表单是否适用于所有场合,但说实话这是非常不可能的!

使用CSS样式表对表单进行样式化是最糟糕的事情。我遇到的唯一主要跨浏览器问题是在样式化FieldSet和Legend元素时。没有真正的黑客,但需要一些工作才能看起来好。


1
这会如何对齐标签? - Tony the Pony
您需要将标签浮动到左侧,将其显示设置为inline-block,然后添加固定宽度。最好为其添加一个类以便于使用CSS进行定位,但该类的最小要求是左边距等于标签的宽度。'form-field' 类应设置 overflow:hidden 以确保清除浮动,并且 form-inputs 类将略微更改以适用于多个字段。祝好 - Hux
这不是对OP问题的答案,因为这需要标签的固定宽度。他写道:“是的,我正在寻找标签的自动调整大小”。 - Peter V. Mørch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接