问题描述
我有一个水平的弹出框(即 flex-direction:row
,即并排)。每个项目可以是单行文本,也可以有多行。
如果每个项目都有一个透明的背景,我可以很容易地使用 align-items: center
。但是,我想让每个项目垂直拉伸,因为我想在整个可用高度上设置一个背景(或者可能是边框,或者是一个可点击区域)。
到目前为止,我知道:
- 扩展:
align-items:stretch
- 对齐:
align-items:center
- 伸展和对齐:
演示可在和和和基本上要求相同的东西,但他们有一个单一的元素或纯文本作为每个flex项。一旦我们有混合内容(可能包含多个元素),这些解决方案就无法正常工作。
解决方案包括:
- 在
上设置
display:flex;
code>。 - 将
< li>
内容封装到另一个元素中。
- 这是必需的,因为
< li>
现在是一个flex容器,因此我们需要另一个元素 - 在此解决方案中,我引入了一个
< div>
元素,但它可以已经是其他元素。
- 这是必需的,因为
- 现在
< li>
容器并且它只包含一个孩子,我们可以使用align-items
和/或justify-content
DOM树看起来像这样:
< ul> flex-parent,direction = row
├< li> flex-item&&灵活父母&背景&& JavaScript可点击区域
│└< div> flex-item作为单个透明元素
│├实际内容
│└实际内容
├...
注意:此答案中的解决方案使用2个嵌套的弹性框。 Michael_B的解决方案使用3个嵌套的弹性框,因为它有扩展< a>
元素以填充整个< li>
。优选哪一种取决于每种情况。如果可以,我会接受这两个答案。
/ *新代码:这是解决方案。 * / ul> li {display:flex; flex-direction:column; justify-content:center; align-items:center;} / *下面的旧代码。 * / ul {display:flex; flex-direction:row; align-items:stretch;} ul> {flex-grow:1; flex-shrink:0; flex-basis:5em; text-align:center;} ul> li:nth-child(2){background:#CFC;} / *视觉风格,只是忽略。 * / html,body {font-family:sans-serif; font-size:25px; } ul,li {list-style:none; margin:0; padding:0; } ul {background:#CCF; width:25em; } button:focus + ul {font-size:14px; width:auto;}
< button& set< code> width:auto< / code>并减小字体大小。< / button><! - 新代码:有一个< div>在每个< li>及其内容。 - >< ul> < li>< div>示例< / div>< / li> < li>< div>< span> span< / span>< / div>< / li> < li>< div>< span> multiple< / span> < span> span< / span>< / div>< / li> < li>< div>文字< span> span< / span>< / div>< / li& < li>< / div>< br />< / div>< / p>
I have a horizontal flex box (i.e. flex-direction: row
, i.e. side-by-side) with a few items. Each item can be a single line of text, or can have multiple lines. I want to vertically-align the contents of each flex item.
If each item had a transparent background, I could easily use align-items: center
. However, I want each item to be stretched vertically, because I want to set a background (or maybe borders, or maybe it is a clickable region) to the entire available height.
So far, I know:
- Stretching:
align-items: stretch
- Aligning:
align-items: center
- Stretching and aligning: ???
Demo available at http://codepen.io/denilsonsa/pen/bVBQNa
ul {
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul.second {
align-items: center;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
<ul class="first">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
<hr>
<ul class="second">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
Similar questions:
- Question 14012030 and question 23442692 and question 27729619 and question 25311541 ask essentially the same thing, but they either have a single element or plain text as child of each flex item. As soon as we have mixed content, possibly with multiple elements, those solutions do not work.
- Question 19026884 is unrelated, the issue there was the wrong markup.
解决方案 Unfortunately, it is impossible to achieve the desired effect while using the exact markup posted in the question.
The solution involves:
- Setting
display: flex;
on <li>
. - Wrapping the
<li>
contents into another element.- This is required because
<li>
is now a flex container, so we need another element to prevent the actual contents from becoming flex items. - In this solution, I introduced a
<div>
element, but it could have been other element.
- Now that
<li>
is a flex container and it contains only a single child, we can use align-items
and/or justify-content
to align this new and only child.
The DOM tree looks like this:
<ul> flex-parent, direction=row
├ <li> flex-item && flex-parent && background && JavaScript clickable area
│ └ <div> flex-item as a single transparent element
│ ├ Actual contents
│ └ Actual contents
├ …
Note: The solution in this answer uses 2 nested flex boxes. The solution by Michael_B uses 3 nested flex boxes, because it has the added challenge of expanding the <a>
element to fill the entire <li>
. Which one is preferred depends on each case. If I could, I would accept both answers.
/* New code: this is the solution. */
ul > li {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* Old code below. */
ul {
display: flex;
flex-direction: row;
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
button:focus + ul {
font-size: 14px;
width: auto;
}
<button>Click here to set <code>width: auto</code> and reduce the font size.</button>
<!-- New code: there is a single <div> between each <li> and their contents. -->
<ul>
<li><div>Sample</div></li>
<li><div><span>span</span></div></li>
<li><div><span>multiple</span> <span>span</span></div></li>
<li><div>text <span>span</span></div></li>
<li><div>multi<br>line</div></li>
</ul>
这篇关于垂直对齐行方向弹性框中的文本,同时也拉伸每个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!