Bagaimana cara membuat item flexbox dengan ukuran yang sama?

186

Saya ingin menggunakan flexbox yang memiliki beberapa item dengan lebar yang sama. Saya perhatikan bahwa flexbox mendistribusikan ruang sekitar secara merata, bukan ruang itu sendiri.

Sebagai contoh:

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

Item pertama jauh lebih besar daripada yang kedua. Jika saya memiliki 3 item, 4 item, atau n item, saya ingin semuanya muncul pada baris yang sama dengan jumlah ruang per item yang sama.

Ada ide?

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

Chet
sumber

Jawaban:

287

Mengatur mereka sehingga mereka flex-basisadalah 0(sehingga semua elemen memiliki titik awal yang sama), dan memungkinkan mereka untuk tumbuh:

flex: 1 1 0px

IDE atau linter Anda mungkin menyebutkan itu the unit of measure 'px' is redundant. Jika Anda membiarkannya (seperti flex: 1 1 0:), IE tidak akan membuat ini dengan benar. Jadi pxdiperlukan untuk mendukung Internet Explorer, sebagaimana disebutkan dalam komentar oleh @fabb;

Adam
sumber
65
Perlu dicatat bahwa flexproperti adalah properti singkatan untuk flex-grow, flex-shrinkdan flex-basisproperti. Dianjurkan untuk menggunakan steno di atas properti individual karena steno dengan benar mengatur ulang setiap komponen yang tidak ditentukan untuk mengakomodasi penggunaan umum. Nilai awal adalah 0 1 auto.
j08691
3
perhatikan bahwa IE11 mengabaikan nilai-nilai basis-fleksibel unitless: github.com/philipwalton/flexbugs#flexbug-4
fabb
9
Saya harus menambahkan min-width: 0untuk mencapai menggunakan elemen anak dengan teks meluap. Lihat css-tricks.com/flexbox-truncated-text
Iwazaru
78

Anda dapat menambahkan flex-basis: 100%untuk mencapai ini.

Contoh yang Diperbarui

.header {
  display: flex;
}

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

Untuk apa nilainya, Anda juga bisa menggunakan flex: 1untuk hasil yang sama.

Singkatan dari flex: 1sama dengan flex: 1 1 0, yang setara dengan:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  text-align: center;
  border: 1px solid black;
}
Josh Crozier
sumber
1
Ini tidak benar. Nilai flex standar adalah flex: 0 1 auto. Yang berarti pengaturan flex: 1akan menghasilkan flex: 1 1 auto. Ini tidak akan berfungsi. Jawaban yang benar adalah flex: 1 1 0seperti yang dinyatakan di atas oleh Adam
r.sendecky
17
@ r.sendecky Tidak, kaulah yang salah. Seperti yang saya nyatakan dalam jawaban saya, singkatan flex: 1hasil flex: 1 1 0 tidak flex: 1 1 auto seperti yang Anda klaim. Lihatlah spesifikasi W3 resmi di bawah bagian 'steno cepat' : kapan flex-basis"dihilangkan dari sten fleks, nilai yang ditentukan adalah 0", tidak auto. Terima kasih atas downvote acak.
Josh Crozier
2
@ r.sendecky - Lihat juga contoh yang saya buat untuk memvisualisasikan variasi ini.
Josh Crozier
1
Mate, aku tidak melakukan voting acak. Saya menguji sebelum saya menulis. Dan saya memang mengujinya. Jawaban Anda tidak berfungsi - sesederhana itu. Saya memiliki masalah yang sama belum lama ini dengan flex: 1dan flex-direction: column. Ketinggian anak-anak tidak sama ketika elemen-elemen lain ditempatkan di dalam anak-anak. Satu-satunya hal yang memperbaikinya adalah pengaturan flex: 1 1 0. Masih berdiri hari ini dengan chromium 55.0.2883.87
r.sendecky
4
@JoshCrozier mengonfirmasi bahwa flex: 1memiliki perilaku yang sama dengan flex: 1 1 0, dan flex: 0 1 automemiliki perilaku yang berbeda.
Ivan Durst
66

Anda perlu menambahkan width: 0untuk membuat kolom sama jika konten item membuatnya bertambah besar.

.item {
  flex: 1 1 0;
  width: 0;
}
Jason Song
sumber
5
Ini tampaknya diperlukan jika isi dari .itempenyebabnya tumbuh lebih luas dari yang .itemseharusnya.
Bungle
1
Saya pikir maksud Anda flex: 1 1 0;, alih-alihflex-grow: 1 1 0;
Sup Ayam
3
fyi, tautan rusak
Bobby Jack
mengatur flex-basisuntuk 0melayani tujuan yang sama seperti mengatur widthuntuk 0.
Stephen
Dalam kasus penggunaan saya, saya membungkus grafik yang secara dinamis menyesuaikan dengan ukuran dan lebar orangtua mereka 0 diperlukan agar mereka dapat bekerja. Saya tidak yakin bagaimana mereka menentukan lebar yang tepat, tetapi dasar flex jelas tidak bekerja pada chrome 72 (dirilis Jan 2019).
Andy Groff
12

Jawaban yang diterima oleh Adam (flex: 1 1 0 ) bekerja dengan sempurna untuk wadah flexbox yang lebarnya ditetapkan, atau ditentukan oleh leluhur. Situasi di mana Anda ingin anak-anak sesuai dengan wadah.

Namun, Anda mungkin memiliki situasi di mana Anda ingin wadah tersebut cocok untuk anak-anak, dengan anak-anak berukuran sama berdasarkan anak terbesar. Anda dapat membuat wadah flexbox yang pas untuk anak-anaknya dengan:

  • pengaturan position: absolutedan bukan pengaturan widthatau right, atau
  • letakkan di dalam pembungkus display: inline-block

Untuk wadah flexbox seperti itu, jawaban yang diterima TIDAK bekerja, anak-anak tidak berukuran sama. Saya kira ini adalah batasan flexbox, karena berperilaku sama di Chrome, Firefox dan Safari.

Solusinya adalah dengan menggunakan kisi bukan flexbox.

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
sumber
0

Saya bukan ahli dengan flex tetapi saya sampai di sana dengan menetapkan basis menjadi 50% untuk dua item yang saya hadapi. Tumbuh menjadi 1 dan menyusut ke 0.

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

Steve
sumber