html - 在 CSS 中创建具有右对齐标签和左对齐值的两列布局
问题描述
全部,
在 HTML 和 CSS 中创建如下所示的简单布局的最简单方法是什么:
具体来说 - 左侧是右对齐的标签,右侧是左对齐的值。
我不想硬编码左列的宽度——应该根据最长标签的宽度来确定。
我正在寻找一种至少具有合理语义的方法,它适用于屏幕阅读器(例如,屏幕阅读器应该阅读标签,然后是值,而不是所有标签,然后是所有值),并且不需要一大堆额外的<div>
元素。
这似乎是一个相当常见的布局,所以我假设有一个非常简单的方法来做到这一点。但我自己还没有弄清楚。
A<table>
可以完美地工作,但正如每个人都提醒我的那样,永远不要将 a<table>
用于布局。这显然不是表格数据。
提前致谢!
解决方案
有几个选项,使用最少的 HTML;一个使用 CSS Grid,另一个使用 CSS flex-box 布局。
CSS网格:
/* A simple reset to ensure that all elements and
pseudo-elements have their margin and padding
set to zero, and all are using the same box-sizing: */
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* here we set the <form> element's layout to use
grid layout: */
form {
display: grid;
/* we use the repeat() function to create 2 columns,
each column sized with a minimum of 0 width and a
maximum of 1fr; the 'fr' unit is a fractional unit
and here forces each column to take one fractional
unit of the available space to create two equal-sized
columns: */
grid-template-columns: repeat(2, minmax(0, 1fr));
/* we use the 'gap' property (formerly 'grid-gap') to
specify the gap between grid elements; here we have
0.5em above and below and 1em to the left and right: */
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
/* aligning the text to the right of the <label> element: */
text-align: right;
}
label::after {
/* using the 'content' property of the pseudo-element to
add the colon character: */
content: ':'
}
<form>
<!-- using the 'for' attribute to associate the label with the
relevant <input> element; the value of the 'for' attribute
must be equal to the 'id' attribute-value of the relevant
<input> -->
<label for="input1">label</label>
<input type="text" id="input1" placeholder="input 1">
<label for="input2">A longer label</label>
<input type="text" id="input2" placeholder="input 2">
<label for="input3">Another slightly longer label</label>
<input type="text" id="input3" placeholder="input 3">
<label for="input4">A label that goes on, frankly, for quite a bit further than might be common for the average <label> element</label>
<input type="text" id="input4" placeholder="input 4">
</form>
弹性盒:
/* A simple reset to ensure that all elements and
pseudo-elements have their margin and padding
set to zero, and all are using the same box-sizing: */
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* setting the layout of the <form> to flexbox: */
form {
display: flex;
/* allowing the child elements of the <form> to wrap
to new lines when necessary: */
flex-wrap: wrap;
width: 80vw;
margin: 0 auto;
}
/* Setting common properties for the <label> and <input>
elements: */
label,
input {
/* assigning the flex-grow and flex-shrink (respectively)
properties to 1, in order that they grow/shrink by the
same amount relative to each other; and setting the
flex-basis to 40% (the percentage derived from the parent)
in order to assign a width that's too large to accommodate
more than two elements per line: */
flex: 1 1 40%;
/* setting the margin above/below each 'row' to be 0.5em,
and 0 to the left and right: */
margin: 0.5em 0;
}
label {
text-align: right;
/* setting the margin-right of the <label> to 1em to enforce a
gutter between the <label> and the neighbouring <input> (the
CSS Box Alignment module (level 3) introduces the 'gap' property
that can also be used in the flexbox layout (among others) but
that's not yet supported by browsers, so we have to use margins: */
margin-right: 1em;
}
label::after {
content: ':'
}
<form>
<label for="input1">label</label>
<input type="text" id="input1" placeholder="input 1">
<label for="input2">A longer label</label>
<input type="text" id="input2" placeholder="input 2">
<label for="input3">Another slightly longer label</label>
<input type="text" id="input3" placeholder="input 3">
<label for="input4">A label that goes on, frankly, for quite a bit further than might be common for the average <label> element</label>
<input type="text" id="input4" placeholder="input 4">
</form>
现在,对于上述两种方法,有一个要求可能不适合您的用例:<label>
元素必须实现一个for
属性,这要求关联对象<input>
也必须具有一个id
属性(并且这些值必须是等效的)。
为避免这种情况,我们可以改为将 嵌套<input>
在 中<label>
,它会自动关联<label>
and <input>
; 这将提供(可能)更干净的 HTML:
网格,再次:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
/* it's a crude simplification, but effectively we remove
the <label> from the DOM and instead show its contents;
the text portion, and the <input>, become independant
grid-items (sort of): */
display: contents;
}
<form>
<label>label
<input type="text" placeholder="input 1"></label>
<label>A longer label
<input type="text" placeholder="input 2"></label>
<label>Another slightly longer label
<input type="text" placeholder="input 3"></label>
<label>A label that goes on, frankly, for quite a bit further than might be common for the average label element
<input type="text" placeholder="input 4"></label>
</form>
在上面的代码片段中,您可能会注意到:
- 我们不再使用
label::after
插入表示':'
性字符,因为这显然会被放置在<label>
内容之后,在<input>
and 之后会创建另一个网格项(demo),并且 <label>
文本不再右对齐;这是因为text-align
似乎不适用于文本。
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
<form>
<label>label
<input type="text" placeholder="input 1"></label>
<label>A longer label
<input type="text" placeholder="input 2"></label>
<label>Another slightly longer label
<input type="text" placeholder="input 3"></label>
<label>A label that goes on, frankly, for quite a bit further than might be common for the average label element
<input type="text" placeholder="input 4"></label>
</form>
我们可以在视觉上改进一些东西,将 的文本内容包装<label>
在一个元素中,例如<span>
恢复该表示:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
label span::after {
content: ':';
}
<form>
<label><span>label</span>
<input type="text" placeholder="input 1"></label>
<label><span>A longer label</span>
<input type="text" placeholder="input 2"></label>
<label><span>Another slightly longer label</span>
<input type="text" placeholder="input 3"></label>
<label><span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
<input type="text" placeholder="input 4"></label>
</form>
还值得注意的是,CSS Grid 和 CSS Flexbox 都允许我们在浏览器中以不同于在 DOM 中显示的方式重新排列元素;这可以让我们<label>
根据关联的状态来设置元素的样式<input>
,例如,
网格:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
display: grid;
/* to ensure that the layout backfills the empty spaces
created by moving content around: */
grid-auto-flow: dense;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5em 1em;
width: 80vw;
margin: 0 auto;
}
label {
display: contents;
text-align: right;
}
input {
/* positioning the <input> elements in the secpond
grid-track/column: */
grid-column: 2;
}
label span {
/* positioning the <span> elements in the first
grid-track/column: */
grid-column: 1;
}
label span::after {
content: ':';
}
input:placeholder-shown+span {
color: rebeccapurple;
}
input:not(:placeholder-shown)+span {
color: limegreen;
font-weight: bold;
}
input:focus+span,
input:active+span {
color: #f90;
}
<form>
<label>
<input type="text" placeholder="input 1">
<span>label</span>
</label>
<label>
<input type="text" placeholder="input 2">
<span>A longer label</span>
</label>
<label>
<input type="text" placeholder="input 3">
<span>Another slightly longer label</span>
</label>
<label>
<input type="text" placeholder="input 4">
<span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
</label>
</form>
弹性盒:
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
form {
width: 80vw;
margin: 0 auto;
}
label {
display: flex;
margin: 0.5em 0;
}
label span,
label input {
flex: 1 1 50%;
}
label span {
order: 1;
text-align: right;
margin-right: 1em;
}
label input {
order: 2;
}
label span::after {
content: ':';
}
label span::after {
content: ':';
}
input:placeholder-shown+span {
color: rebeccapurple;
}
input:not(:placeholder-shown)+span {
color: limegreen;
font-weight: bold;
}
input:focus+span,
input:active+span {
color: #f90;
}
<form>
<label>
<input type="text" placeholder="input 1">
<span>label</span>
</label>
<label>
<input type="text" placeholder="input 2">
<span>A longer label</span>
</label>
<label>
<input type="text" placeholder="input 3">
<span>Another slightly longer label</span>
</label>
<label>
<input type="text" placeholder="input 4">
<span>A label that goes on, frankly, for quite a bit further than might be common for the average label element</span>
</label>
</form>
但值得注意的是,grid-auto-flow: dense
除了重新排列元素的视觉呈现外,还可能给那些使用屏幕阅读器或键盘交互的网络用户带来问题。因此,虽然它带来了一些漂亮,但值得考虑的是,这种漂亮是否以可用性(以及潜在的法律要求的可访问性)为代价。
此外,在后面的示例中,使用嵌套<span>
元素来允许对元素的文本内容进行样式化<label>
(无论是出于对齐原因,添加':'
字符还是样式化以响应与<input>
元素的交互,这可能是不必要的复杂化一个潜在的“干净”的 HTML 标记。
参考:
- 选择器:
- 特性
- 属性值:
参考书目:
- “网格完整指南。”
- “ Flexbox 完整指南”。
- “弹性盒的基本概念。”
- 《网格布局的基本概念》。
推荐阅读
- python - Python递归函数获取列表中的下一项
- c - ARM GCC 中对 posix_memalign 的未定义引用
- java - Spring Autowiring all beans from Qualifier in Map
- gdb - Qt Creator:发布和调试版本之间的技术差异
- groovy - 使用 Groovy AST 添加字段不会生成 getter 和 setter
- html - bootstrap 4上的水平和垂直居中卡
- excel - Excel VBA:如何从表单方法的代码中引用工作表?
- java - 无法让弹簧启动执行器公开默认端点以外的端点,需要建议
- c# - jquery.datatables 未正确显示
- powerpoint - 使用 OfficeJS 删除或替换 PowerPoint 中的图像