Подтвердить что ты не робот

Сделайте объекты гибкой стрейч полной высоты и вертикально центрируйте их содержимое

У меня есть горизонтальная гибкая коробка (т.е. 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>
4b9b3361

Ответ 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>