在表单中将标签与输入对齐

169
我有一个非常基础和熟知的表单场景,我需要正确地对齐标签和输入。然而,我不知道该怎么做。
我的目标是让标签在右侧与输入对齐。以下是所需结果的示例图片。

enter image description here

我可以为您提供帮助,以下是翻译内容:

我已经为您准备了一个演示示例,方便您更好地理解我现在的情况 - http://jsfiddle.net/WX58z/

片段:

<div class="block">
    <label>Simple label</label>
    <input type="text" />
</div>
<div class="block">
    <label>Label with more text</label>
    <input type="text" />
</div>
<div class="block">
    <label>Short</label>
    <input type="text" />
</div>

8个回答

220

警告:过时的答案

现在你应该绝对避免使用固定宽度。你可以使用flexbox或CSS grid来设计响应式解决方案。请参考其他答案。


一个可能的解决方案:
  • 确定标签元素的合理固定宽度并使用width设置它
  • 给它们display: inline-block
  • 将文本向右对齐

即:

label {
  display: inline-block;
  width: 140px;
  text-align: right;
}​
<div class="block">
    <label>Simple label</label>
    <input type="text" />
</div>
<div class="block">
    <label>Label with more text</label>
    <input type="text" />
</div>
<div class="block">
    <label>Short</label>
    <input type="text" />
</div>

{{link1:JSFiddle}}


4
如果某些标签是复选框或单选按钮,我该如何使其正常工作?这些元素的标签最终会与文本框的标签具有相同的固定宽度,这是不希望看到的。是否有一种方法可以在标签上不使用固定宽度的情况下实现呢? - Rebecca Meritz
@RebeccaMeritz 您是指复选框先出现在标记上,然后才是标签吗?您可以为两者都添加一个类,并分别为它们设置样式。也许您应该就此提出一个新问题 - bfavaretto
2
如何使其响应式?如何处理i18n?我的意思是,不同语言的文本标签长度不同,因此我担心如果文本太长,设置固定宽度填充将不起作用。 - Azimuth
现在,你可能想使用CSS网格。 - bfavaretto
2
这是一个标记固定宽度的问题,应该根据最大标签宽度进行动态设置。 - Samyak Jain
显示剩余5条评论

81

虽然这里的解决方案是可行的,但更近期的技术提供了我认为更好的解决方案。 CSS Grid 布局 让我们能够构建一个更加优雅的解决方案。

下面的 CSS 提供了一个 2 列的“设置”结构,其中第一列应该是右对齐的标签,后面跟着第二列中的一些内容。 更复杂的内容可以通过将其包装在 <div> 中来呈现在第二列中。

[顺便提一下:我使用 CSS 添加了每个标签后面的 “:”,因为这是一个样式元素 - 我的偏好。]

/* CSS */

div.settings {
    display:grid;
    grid-template-columns: max-content max-content;
    grid-gap:5px;
}
div.settings label       { text-align:right; }
div.settings label:after { content: ":"; }
<!-- HTML -->

<div class="settings">
    <label>Label #1</label>
    <input type="text" />

    <label>Long Label #2</label>
    <span>Display content</span>

    <label>Label #3</label>
    <input type="text" />
</div>


1
嘿,你能加一个fiddle吗? - Stan
是的,我已经更新了答案,使用了代码片段。 - David Rutherford
你使用的是哪个Chrome版本和平台? - David Rutherford
2
最佳解决方案!现在在Chrome 73中运行良好。 - Philipp Michalski
1
太棒了!如果你用 grid-template-columns: max-content 1fr; 替换上面的列定义,第二列会使用所有剩余的宽度。对我来说,这是这种布局的终极目标,在这种情况下不需要指定任何列或内容宽度,一切都能自动地完美适应可用空间。 - jeff-h
1
很抱歉投下反对票,因为CSS网格仍然只是候选推荐草案;它不是那么“最近的技术”,而是“未来的技术”,采用仍然存在风险。 - Philippe Cloutier

14

之前回答过类似的问题,你可以在这里查看结果:

Creating form to have fields and text next to each other - what is the semantic way to do it?

所以,要将同样的规则应用于你的fiddle,你可以使用display:inline-block来使标签和输入组并排显示,就像这样:

CSS

input {
    margin-top: 5px;
    margin-bottom: 5px;
    display:inline-block;
    *display: inline;     /* for IE7*/
    zoom:1;              /* for IE7*/
    vertical-align:middle;
    margin-left:20px
}

label {
    display:inline-block;
    *display: inline;     /* for IE7*/
    zoom:1;              /* for IE7*/
    float: left;
    padding-top: 5px;
    text-align: right;
    width: 140px;
}

更新后的代码


2
这是一个非常好的解决方案,除了你必须硬编码标签的宽度之外。如果新标签太长 - 布局就会破裂。似乎应该有一个更健壮的解决方案? - mattstuehler

10

我使用类似这样的东西:

<div class="form-element">
  <label for="foo">Long Label</label>
  <input type="text" name="foo" id="foo" />
</div>

样式:

.form-element label {
    display: inline-block;
    width: 150px;
}

该方法存在的主要问题在于你使用了固定的宽度,需要不断重新评估标签变化。 - Philippe Cloutier

6

我知道这是一个老帖子,但更简单的解决方案是在标签内嵌入输入框,如下所示:

<label>Label one: <input id="input1" type="text"></label>


我正在寻找一个解决方案(在标签内包含输入),但要求文本对齐。 - Natim
这不符合OP对齐的要求(除非所有标签的宽度都相同)。 - Philippe Cloutier

5
您可以尝试使用 flex-box。
<head><style>
body {
    color:white;
    font-family:arial;
    font-size:1.2em;
}
form {
    margin:0 auto;
    padding:20px;
    background:#444;
}
.input-group {
    margin-top:10px;
    width:60%;
    display:flex;
    justify-content:space-between;
    flex-wrap:wrap;
}
label, input {
    flex-basis:100px;
}
</style></head>
<body>

<form>
    <div class="wrapper">
        <div class="input-group">
            <label for="user_name">name:</label>
            <input type="text" id="user_name">
        </div>
        <div class="input-group">
            <label for="user_pass">Password:</label>
            <input type="password" id="user_pass">
        </div>
    </div>
</form>

</body>
</html>

这很漂亮,但不是他要求的。请参见原帖中的图片。 - phorgan1
CSS 的弹性盒布局模块仅是 W3C 的候选建议,使用它可能无法保证未来兼容性。 - Philippe Cloutier

2
最初的回答:你可以像这样做:
HTML:
<div class='div'>
<label>Something</label>
<input type='text' class='input'/>
<div>

CSS:

.div{
      margin-bottom: 10px;
      display: grid;
      grid-template-columns: 1fr 4fr;
}

.input{
       width: 50%;
}

最初的回答。希望这可以帮到你! :)

0

这里是所有表单标签的通用标签宽度,没有固定宽度。

调用setLabelWidth计算器并将其应用于所有标签。 此函数将在UI上加载所有标签并找出最大标签宽度。 将下面函数的返回值应用于所有标签。

     this.setLabelWidth = function (labels) {
            var d = labels.join('<br>'),
                dummyelm = jQuery("#lblWidthCalcHolder"),
                width;
            dummyelm.empty().html(d);
            width = Math.ceil(dummyelm[0].getBoundingClientRect().width);
            width = width > 0 ? width + 5: width;
            //this.resetLabels(); //to reset labels.
            var element = angular.element("#lblWidthCalcHolder")[0];
            element.style.visibility = "hidden";
            //Removing all the lables from the element as width is calculated and the element is hidden
            element.innerHTML = "";
            return {
                width: width,
                validWidth: width !== 0
            };

        };

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