Jak sprawić, by elementy Flexbox miały ten sam rozmiar?

186

Chcę użyć flexbox, który ma pewną liczbę elementów o tej samej szerokości. Zauważyłem, że flexbox rozdziela przestrzeń równomiernie, a nie samą przestrzeń.

Na przykład:

.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>

Pierwsza pozycja jest dużo większa niż druga. Jeśli mam 3 elementy, 4 elementy lub n elementów, chcę, aby wszystkie pojawiały się w tym samym wierszu z jednakową ilością miejsca na element.

Jakieś pomysły?

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

Chet
źródło

Odpowiedzi:

287

Ustaw je tak, że ich flex-basisjest 0(tak, wszystkie elementy mają ten sam punkt początkowy) i pozwolić im się rozwijać:

flex: 1 1 0px

Twoje IDE lub linter mogą o tym wspomnieć the unit of measure 'px' is redundant. Jeśli go pominiesz (na przykład flex: 1 1 0:), IE nie wyrenderuje tego poprawnie. Tak więc pxwymagana jest obsługa przeglądarki Internet Explorer, jak wspomniano w komentarzach @fabb;

Adam
źródło
65
Należy zauważyć, że flexwłaściwość jest skróconą własnością właściwości flex-grow, flex-shrinki flex-basis. Zaleca się używanie skrótu do poszczególnych właściwości, ponieważ skrót poprawnie resetuje wszystkie nieokreślone komponenty, aby dostosować się do typowych zastosowań. Wartość początkowa to 0 1 auto.
j08691
3
zwróć uwagę, że IE11 ignoruje bezjednostkowe wartości flex- base
fabb
9
Musiałem coś dodać, min-width: 0aby osiągnąć użycie elementów potomnych z przepełnionym tekstem. Zobacz css-tricks.com/flexbox-truncated-text
Iwazaru
77

Możesz dodać, flex-basis: 100%aby to osiągnąć.

Zaktualizowany przykład

.header {
  display: flex;
}

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

Za to, co jest warte, możesz również użyć flex: 1dla tych samych wyników.

Skrót od flex: 1jest taki sam jak flex: 1 1 0, co jest równoważne z:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  text-align: center;
  border: 1px solid black;
}
Josh Crozier
źródło
1
To nie jest poprawne. Domyślna wartość flex to flex: 0 1 auto. Co oznacza, że ​​ustawienie flex: 1spowoduje flex: 1 1 auto. To nie zadziała. Prawidłowa odpowiedź jest taka, flex: 1 1 0jak podano powyżej Adam
r.sendecky
17
@ r.sendecky Nie, to ty nie masz racji. Jak powiedziałem w mojej odpowiedzi, skrót flex: 1wyników flex: 1 1 0 nie jest flex: 1 1 auto taki, jak twierdzisz. Spójrz na oficjalną specyfikację W3 w sekcji „flex shorthand” : kiedy flex-basisjest „pominięte w skrócie flex, jego określona wartość to 0”, nie auto. Dzięki za losowy głos przeciw.
Josh Crozier
2
@ r.sendecky - Spójrz również na ten przykład, który stworzyłem, aby zwizualizować odmiany.
Josh Crozier
1
Stary, nie głosuję losowo. Testuję, zanim napiszę. I przetestowałem to. Twoja odpowiedź nie działa - proste. Niedawno miałem dokładnie ten sam problem z flex: 1i flex-direction: column. Wysokość dzieci nie była taka sama, gdy inne elementy są umieszczane w dzieciach. Jedyną rzeczą, która go naprawiła, było ustawienie flex: 1 1 0. Nadal stoi dzisiaj z chromem 55.0.2883.87
r.sendecky
4
@JoshCrozier potwierdził, że flex: 1zachowuje się tak samo jak flex: 1 1 0i flex: 0 1 autozachowuje się inaczej.
Ivan Durst
66

Musisz dodać, width: 0aby kolumny były równe, jeśli zawartość elementów powoduje, że rosną.

.item {
  flex: 1 1 0;
  width: 0;
}
Jason Song
źródło
5
Wydaje się to być konieczne, jeśli zawartość .itempowoduje, że rozszerza się on bardziej niż .itembyłoby to naturalne.
Bungle
1
Myślę, że masz na myśli flex: 1 1 0;, zamiastflex-grow: 1 1 0;
Zupa z kurczaka,
3
fyi, link jest uszkodzony
Bobby Jack
ustawienie flex-basisdo 0służy temu samemu celowi co ustawienie widthdo 0.
Stephen
W moim przypadku zawijałem wykresy, które dynamicznie dostosowują się do rozmiaru ich rodzica, a szerokość 0 była niezbędna do ich działania. Nie jestem pewien, jak określili odpowiednią szerokość, ale podstawa flex z pewnością nie działała na chrome 72 (wydany w styczniu 2019).
Andy Groff
12

Zaakceptowana odpowiedź Adama ( flex: 1 1 0) działa doskonale w przypadku kontenerów typu flexbox, których szerokość jest stała lub określona przez przodka. Sytuacje, w których chcesz, aby dzieci pasowały do ​​pojemnika.

Może się jednak zdarzyć, że chcesz, aby pojemnik pasował do dzieci, a dzieci powinny mieć równe rozmiary w oparciu o największe dziecko. Możesz dopasować kontener typu flexbox do swoich elementów podrzędnych:

  • ustawienie, position: absolutea nie ustawienie widthlub right, lub
  • umieść go w opakowaniu z display: inline-block

W przypadku takich pojemników typu flexbox przyjęta odpowiedź NIE działa, dzieci nie mają równych rozmiarów. Przypuszczam, że jest to ograniczenie flexboksa, ponieważ zachowuje się tak samo w Chrome, Firefox i Safari.

Rozwiązaniem jest użycie siatki zamiast flexboksa.

Demo: 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;
}
Brett Donald
źródło
0

Nie jestem ekspertem w dziedzinie flex, ale osiągnąłem to, ustawiając podstawę na 50% dla dwóch rzeczy, z którymi miałem do czynienia. Rosną do 1 i zmniejszają się do 0.

Stylizacja inline: flex: '1 0 50%',

Steve
źródło