Сделайте объекты гибкой стрейч полной высоты и вертикально центрируйте их содержимое
У меня есть горизонтальная гибкая коробка (т.е. flex-direction: row
, то есть бок о бок) с несколькими элементами. Каждый элемент может быть одной строкой текста или может иметь несколько строк. Я хочу вертикально выровнять содержимое каждого элемента flex.
Если каждый элемент имел прозрачный фон, я мог бы легко использовать align-items: center
. Тем не менее, я хочу, чтобы каждый элемент растягивался вертикально, потому что я хочу установить фон (или, может быть, границы или, возможно, это область с кликом) на всю доступную высоту.
До сих пор я знаю:
- Растяжка:
align-items: stretch
- Выравнивание:
align-items: center
- Растяжение и выравнивание:
Демонстрация доступна на http://codepen.io/denilsonsa/pen/bVBQNa
![Screenshot of the demo]()
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>
Ответы
Ответ 1
К сожалению, невозможно добиться желаемого эффекта при использовании точной разметки, размещенной в вопросе.
Решение включает в себя:
- Настройка
display: flex;
на <li>
.
- Обтекание содержимого
<li>
в другом элементе.
- Это необходимо, потому что
<li>
теперь является контейнером flex, поэтому нам нужен еще один элемент, чтобы исключить фактическое содержимое из элементов flex.
- В этом решении я ввел элемент
<div>
, но это мог быть другой элемент.
- Теперь, когда
<li>
является контейнером flex и содержит только один дочерний элемент, мы можем использовать align-items
и/или justify-content
для выравнивания этого нового и единственного дочернего элемента.
Дерево DOM выглядит так:
<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
├ …
Примечание. Решение в этом ответе использует 2 вложенных флекса. Решение Michael_B использует 3 вложенных флекса, потому что у него есть дополнительная задача расширения элемента <a>
для заполнения всего <li>
. Какой из них предпочтительнее, зависит от каждого случая. Если бы я мог, я бы принял оба ответа.
/* 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>
Ответ 2
Сделайте контейнеры li
flex с flex-direction:column
. Я думаю, что вы после.
html,
body {
font-family: sans-serif;
font-size: 25px;
}
ul,
li {
list-style: none;
margin: 0;
padding: 0;
}
ul {
background: #CCF;
width: 25em;
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
/*outline: 1px dotted #444;*/
}
ul > li:nth-child(2) {
background: #CFC;
}
<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>
Ответ 3
Я хочу, чтобы каждый элемент растягивался вертикально, потому что я хочу установить фон (или, может быть, границы, или, возможно, это область с кликами), чтобы всей доступной высоты.
Вы можете достичь этого макета без каких-либо изменений в своей структуре HTML. Нет необходимости в дополнительных контейнерах.
У вас уже есть основной контейнер flex и группа элементов flex. Просто сделайте эти гибкие элементы во вложенные контейнеры flex. Это позволит вам выровнять контент со свойствами flex.
(Поскольку вы упомянули, что вам могут потребоваться области с кликами, я переключился с li
на a
.)
nav {
display: flex;
background: #CCF;
width: 25em;
}
nav > a {
flex: auto; /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
text-align: center;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
}
nav > a:nth-child(2) {
background: #CFC;
}
html, body {
font-family: sans-serif;
font-size: 25px;
}
<nav>
<a href="">Sample</a>
<a href=""><span>span</span></a>
<a href=""><span>multiple</span> <span>span</span></a>
<a href="">text <span>span</span></a>
<a href="">multi<br>line</a>
</nav>
Ответ 4
Элементы Flex-child также могут быть гибкими родительскими элементами.
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-family: sans-serif;
font-size: 25px;
}
body {
display: flex;
flex-flow: column nowrap;
background-color: #333;
overflow: hidden;
}
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.List {
padding: 0;
margin: 0;
background: #CCF;
width: 25em;
list-style: none;
display: flex;
flex-flow: row nowrap;
justify-content: center;
}
.ListItem {
flex-basis: 5em;
display: flex;
flex-flow: row wrap;
text-align: center;
align-items: center;
}
.ListItem:nth-child(2) {
background: #CFC;
}
.ListItem__content {
width: 100%;
}
<ul class="List">
<li class="ListItem">
<span class="ListItem__content">Sample</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multiple <br> span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multi<br>line</span></li>
</ul>