Как сделать флексбоксы одинакового размера?

187

Я хочу использовать flexbox с некоторым количеством элементов одинаковой ширины. Я заметил, что flexbox распределяет пространство вокруг равномерно, а не само пространство.

Например:

.header {
  display: flex;
}

.item {
  flex-grow: 1;
  text-align: center;
  border: 1px solid black;
}
<div class="header">
  <div class="item">asdfasdfasdfasdfasdfasdf</div>
  <div class="item">z</div>
</div>

Первый элемент намного больше, чем второй. Если у меня есть 3 предмета, 4 предмета или n предметов, я хочу, чтобы все они отображались в одной строке с одинаковым количеством места на предмет.

Любые идеи?

http://codepen.io/anon/pen/gbJBqM

Chet
источник

Ответы:

287

Установите их так , что их flex-basisесть 0(так что все элементы имеют одинаковую начальную точку), и позволить им расти:

flex: 1 1 0px

Ваша IDE или линтер могут упомянуть об этом the unit of measure 'px' is redundant. Если вы пропустите это (например:) flex: 1 1 0, IE не будет отображать это правильно. Таким образом, pxтребуется поддержка Internet Explorer, как указано в комментариях @fabb;

Адам
источник
65
Следует отметить , что flexсвойство является сокращенным свойством для flex-grow, flex-shrinkи flex-basisсвойств. Рекомендуется использовать сокращение над отдельными свойствами, так как сокращение корректно сбрасывает любые неопределенные компоненты, чтобы приспособиться к общему использованию. Начальное значение 0 1 auto.
j08691
3
обратите внимание, что IE11 игнорирует безблокированные значения flex-based: github.com/philipwalton/flexbugs#flexbug-4
fabb
9
Мне пришлось добавить, min-width: 0чтобы добиться использования дочерних элементов с переполнением текста. См. Css-tricks.com/flexbox-truncated-text
Ивазару,
78

Вы можете добавить, flex-basis: 100%чтобы достичь этого.

Обновленный пример

.header {
  display: flex;
}

.item {
  flex-basis: 100%;
  text-align: center;
  border: 1px solid black;
}

Что бы это ни стоило, вы также можете использовать flex: 1для тех же результатов.

Сокращение flex: 1такое же, как flex: 1 1 0, что эквивалентно:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  text-align: center;
  border: 1px solid black;
}
Джош Крозье
источник
1
Это не правильно. Значение по умолчанию flex flex: 0 1 auto. Что означает, что настройка flex: 1приведет к flex: 1 1 auto. Это не будет работать. Правильный ответ, flex: 1 1 0как указано выше, Адам
r.sendecky
17
@ r.sendecky Нет, ты тот, кто не прав. Как я уже сказал в своем ответе, сокращение flex: 1результатов flex: 1 1 0 не так, flex: 1 1 auto как вы утверждаете. Взгляните на официальную спецификацию W3 в разделе «flex shorthand» : когда flex-basis«опущено в flex-стенограмме, его указанное значение равно 0», а не auto. Спасибо за случайное понижение.
Джош Крозье
2
@ r.sendecky - также посмотрите на этот пример, который я создал, чтобы визуализировать варианты.
Джош Крозье
1
Дружище, я не делаю случайного понижающего голоса. Я проверяю, прежде чем писать. И я это проверил. Ваш ответ не работает - просто так. У меня была точно такая же проблема не так давно с flex: 1и flex-direction: column. Высота дочерних элементов не была одинаковой, когда другие элементы помещались в дочерние элементы. Единственное, что исправило это, было установка flex: 1 1 0. Это все еще стоит сегодня с хромом 55.0.2883.87
r.sendecky
4
@JoshCrozier подтвердил, что flex: 1имеет то же поведение flex: 1 1 0, что и flex: 0 1 autoдругое поведение.
Иван Дерст
66

Вы должны добавить, width: 0чтобы сделать столбцы равными, если содержимое элементов увеличивает их.

.item {
  flex: 1 1 0;
  width: 0;
}
Джейсон Сонг
источник
5
По-видимому, это необходимо, если его содержание станет .itemшире, чем .itemобычно.
Bungle
1
Я думаю, что вы имеете в виду flex: 1 1 0;, вместоflex-grow: 1 1 0;
куриный суп
3
Кстати, ссылка не работает
Бобби Джек,
установка flex-basisдля 0служит той же цели, что и установка widthдля 0.
Стивен
В моем случае использования я оборачивал диаграммы, которые динамически приспосабливались к размеру их родителей и ширине 0, чтобы они работали. Я не уверен, как они определяли правильную ширину, но гибкая основа определенно не работала на Chrome 72 (выпущен в январе 2019 года).
Энди Грофф
12

Принятый ответ Adam ( flex: 1 1 0) отлично работает для контейнеров flexbox, ширина которых либо фиксирована, либо определена предком. Ситуации, когда вы хотите, чтобы дети помещались в контейнер.

Однако может возникнуть ситуация, когда вы хотите, чтобы контейнер соответствовал дочерним элементам, при этом размер дочерних элементов будет одинаковым по размеру в зависимости от наибольшего дочернего элемента. Вы можете сделать контейнер flexbox соответствующим его потомкам:

  • установка, position: absoluteа не установка widthили right, или
  • поместите его в обертку с display: inline-block

Для таких контейнеров flexbox принятый ответ НЕ работает, дочерние элементы имеют одинаковый размер. Я предполагаю, что это ограничение flexbox, так как он ведет себя одинаково в Chrome, Firefox и Safari.

Решение состоит в том, чтобы использовать сетку вместо flexbox.

Демо: https://codepen.io/brettdonald/pen/oRpORG

<p>Normal scenario — flexbox where the children adjust to fit the container — and the children are made equal size by setting {flex: 1 1 0}</p>

<div id="div0">
  <div>
    Flexbox
  </div>
  <div>
    Width determined by viewport
  </div>
  <div>
    All child elements are equal size with {flex: 1 1 0}
  </div>
</div>

<p>Now we want to have the container fit the children, but still have the children all equally sized, based on the largest child. We can see that {flex: 1 1 0} has no effect.</p>

<div class="wrap-inline-block">
<div id="div1">
  <div>
    Flexbox
  </div>
  <div>
    Inside inline-block
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
</div>

<div id="div2">
  <div>
    Flexbox
  </div>
  <div>
    Absolutely positioned
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>

<br><br><br><br><br><br>
<p>So let's try a grid instead. Aha! That's what we want!</p>

<div class="wrap-inline-block">
<div id="div3">
  <div>
    Grid
  </div>
  <div>
    Inside inline-block
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
</div>

<div id="div4">
  <div>
    Grid
  </div>
  <div>
    Absolutely positioned
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
body {
  margin: 1em;
}

.wrap-inline-block {
  display: inline-block;
}

#div0, #div1, #div2, #div3, #div4 {
  border: 1px solid #888;
  padding: 0.5em;
  text-align: center;
  white-space: nowrap;
}

#div2, #div4 {
  position: absolute;
  left: 1em;
}

#div0>*, #div1>*, #div2>*, #div3>*, #div4>* {
  margin: 0.5em;
  color: white;
  background-color: navy;
  padding: 0.5em;
}

#div0, #div1, #div2 {
  display: flex;
}

#div0>*, #div1>*, #div2>* {
  flex: 1 1 0;
}

#div0 {
  margin-bottom: 1em;
}

#div2 {
  top: 15.5em;
}

#div3, #div4 {
  display: grid;
  grid-template-columns: repeat(3,1fr);
}

#div4 {
  top: 28.5em;
}
Бретт Дональд
источник
0

Я не эксперт по флексу, но я получил это, установив основу на 50% для двух предметов, с которыми я имел дело. Вырасти до 1 и уменьшись до 0.

Встроенный стиль: flex: '1 0 50%',

Стив
источник