并排排列标签和输入的最佳方式



不使用表格或display:table,是否可以在输入左侧为标签设置灵活的宽度区域? 出于浏览器兼容性原因,我还想避免网格布局。 我希望 css 处理这个问题:

short_label   input_box____________________
tiny_label    input_box____________________
medium_label  input_box____________________

然后相应地处理更大的标签:

short_label            input_box__________
medium_label           input_box__________
very_extra_long_label  input_box__________

但我不想要

short_label            input_box__________
tiny_label             input_box__________
medium_label           input_box__________

因此,第一列需要具有灵活的宽度,第二列需要增长以填充空间。理想情况下,我的 html 看起来像这样,但如有必要,可以添加"行"div。 我觉得有一个灵活的答案,但也许不是,因为所有行都需要对齐。

<div class='aligned_form'>
<label for='a'>short_label</label>
<input type='text' id='a'>
<label for='b'>medium_label</label>
<input type='text' id='b'>
<label for='c'>very_extra_long_label</label>
<input type='text' id='c'>
</div>

align-items: stretch

弹性框具有通常称为"等高列"的功能。此功能使同一容器中的弹性项目高度相等。

此功能来自两个初始设置:

  • flex-direction: row
  • align-items: stretch

稍作修改,此功能即可变为"等宽行"。

  • flex-direction: column
  • align-items: stretch

现在,一列弹性项目将具有最长项目的宽度。

参考:

  • 带弹性框的等高列

align-content: stretch

弹性容器上的初始设置为align-content: stretch。此设置将在容器的长度上分布行或列(取决于flex-direction(。

在这种情况下,为了将两列打包到容器的开头,我们需要用align-content: flex-start覆盖默认值。

引用:

  • 在多行弹性项目换行时删除它们之间的空间(间隙(
  • 弹性换行如何与对齐、对齐项目和对齐内容配合使用?

flex-direction: columnflex-wrap: wrapheight

由于您具有首选的HTML结构(所有表单元素在一个容器中按逻辑顺序排序(,因此flex项目需要换行以形成标签列和输入列。

所以我们需要用wrap覆盖flex-wrap: nowrap(默认值(。

此外,容器必须具有固定高度,以便物品知道在哪里包装。

引用:

  • 弹性项目是否可以与其上方的项目紧密对齐?
  • 使div 跨越网格中的两行

order属性

需要order属性才能跨列正确对齐标签和输入。

参考:

  • 是否有"前兄弟姐妹"CSS选择器?

.aligned_form {
display: flex;
flex-flow: column wrap;
align-content: flex-start;
height: 75px;
}
label[for='a'] { order: -3; }
label[for='b'] { order: -2; }
label[for='c'] { order: -1; }
label, input {
height: 25px;
padding: 5px;
box-sizing: border-box;
}
<!-- No changes to the HTML. -->
<div class='aligned_form'>
<label for='a'>short_label</label>
<input type='text' id='a' placeholder="short_label">
<label for='b'>medium_label</label>
<input type='text' id='b' placeholder="medium_label">
<label for='c'>very_extra_long_label</label>
<input type='text' id='c' placeholder="very_extra_long_label">
</div>

jsFiddle 演示 1


更改 HTML 结构

如果您可以更改 HTML,这里有一个替代解决方案。

  • 一个主弹性容器,其中包含两个弹性项目列(标签和输入(
  • flex: 1添加到输入列,以便它占用行中的所有可用空间,并将标签列打包到其最长项目的宽度

form {
display: flex;
}
form > div {
display: flex;
flex-direction: column;
}
form > div:last-child {
flex: 1;
}
label, input {
height: 25px;
padding: 5px;
box-sizing: border-box;
}
<form>
<div>
<label for='a'>short_label</label>
<label for='b'>medium_label</label>
<label for='c'>very_extra_long_label</label>
</div>
<div>
<input type='text' id='a' placeholder="short_label">
<input type='text' id='b' placeholder="medium_label">
<input type='text' id='c' placeholder="very_extra_long_label">
</div>
</form>

js小提琴演示 2

我知道你说你不想要CSS网格布局,但出于文档目的,我将在这里添加它。因为我认为如果您不介意支持问题,这是最干净的解决方案。

您始终可以通过将1fr输入替换为像素或其他值来设置输入的固定宽度。此外,align-self是将标签和输入垂直居中,如果您希望将center更改为end。 这也使HTML保持超级干净!

.container{
display: grid;
grid-gap: 10px;
grid-template-columns: [label] auto [input] 1fr;
}
input {
grid-column: input;
align-self: center;
}
label {
grid-column: label;
align-self: center;
}
<div class="container">
<label for='a'>short_label</label>
<input type='text' id='a'>
<label for='b'>medium_label</label>
<input type='text' id='b'>
<label for='c'>very_extra_long_label</label>
<input type='text' id='c'>
</div>

我认为@Michael_B的解决方案很棒,但另一种方法是创建一个包含 2 列的弹性行,然后将每一列都设为弹性列。只需在label/input上设置一个高度,使它们保持一致,然后调整边距。

<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<style>
label,input {
height: 25px;
margin:0 0 .5em;
}
label {
margin-right: .5em;
}
</style>
<div class="container">
<div class="row">
<div class="d-flex flex-column">
<label for='a'>short_label</label>
<label for='b'>medium_label</label>
<label for='c'>very_extra_long_label</label>
</div>
<div class="d-flex flex-column">
<input type='text' id='a'>
<input type='text' id='b'>
<input type='text' id='c'>
</div>
</div>
</div>

最新更新