Cara yang lebih baik untuk mengatur jarak antara item-item flexbox


781

Untuk mengatur jarak minimal antara item-item flexbox yang saya gunakan margin: 0 5pxdi .itemdan margin: 0 -5pxdi wadah. Bagi saya, ini seperti retasan, tetapi saya tidak dapat menemukan cara yang lebih baik untuk melakukan ini.

Contoh

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  margin: 0 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>


29
Ini bukan peretasan - ini adalah salah satu metode yang dimaksudkan untuk menyelaraskan item. Ada properti lain. Lihat w3.org/TR/css3-flexbox/#alignment
BoltClock

4
Ya saya mengerti. Tapi misalnya ada properti gap-kolom yang memberi kita kemampuan untuk mengontrol jarak dari kontainer: w3.org/TR/css3-multicol/#column-gap
Sasha Koss

Karena itu adalah margin runtuh dari flexbox. Pertanyaan lain memiliki awser kanan [Bagaimana saya bisa menghentikan margin terakhir runtuh di flexbox? ] ( stackoverflow.com/questions/38993170/… )
Jack Yang

6
The CSS Box Penyelarasan Modul Level 3 meliputi bagian pada kesenjangan antara kotak - yang berlaku untuk unsur-unsur multi-kolom, wadah fleksibel , dan wadah jaringan. Jadi pada akhirnya ini akan menjadi sederhana seperti: row-gap: 5px- selesai.
Danield

2
@JohnCarrell firefox sebenarnya sudah mendukung gapproperti pada wadah fleksibel ( caniuse )
Danield

Jawaban:


428
  • Flexbox tidak memiliki margin runtuh.
  • Flexbox tidak memiliki apa pun yang mirip dengan border-spacingtabel (kecuali untuk properti CSS gapyang tidak didukung dengan baik di sebagian besar peramban, caniuse )

Karena itu, mencapai apa yang Anda minta sedikit lebih sulit.

Dalam pengalaman saya, cara "terbersih" yang tidak menggunakan :first-child/ :last-childdan berfungsi tanpa modifikasi apa pun flex-wrap:wrapadalah dengan memasang padding:5pxwadah dan margin:5pxanak-anak. Itu akan menghasilkan 10pxkesenjangan antara setiap anak dan antara setiap anak dan orang tua mereka.

Demo

.upper
{
  margin:30px;
  display:flex;
  flex-direction:row;
  width:300px;
  height:80px;
  border:1px red solid;

  padding:5px; /* this */
}

.upper > div
{
  flex:1 1 auto;
  border:1px red solid;
  text-align:center;

  margin:5px;  /* and that, will result in a 10px gap */
}

.upper.mc /* multicol test */
{flex-direction:column;flex-wrap:wrap;width:200px;height:200px;}
<div class="upper">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>

<div class="upper mc">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>


220
Ini tidak mencapai hal yang sama dengan pertanyaan yang diajukan, Anda akan memiliki indentasi 10px di paling kiri dan kanan, yang saya asumsikan tidak mereka inginkan. Oleh karena itu, margin negatif dalam pertanyaan awal.
Chris Nicola

17
Bagaimana jika orderproperti diatur? :first-child/:last-childtidak akan berfungsi seperti yang diharapkan.
Guria

4
"Flexbox tidak memiliki margin yang runtuh." Sangat berwawasan luas, dan tampaknya benar, tetapi dapatkah saya meminta kutipan?
chharvey

2
Bukankah ini jawaban yang lebih buruk daripada pertanyaan aslinya? Metode ini mengharuskan Anda memiliki ruang di sekitar wadah dan talang air harus selalu berupa bilangan genap.
limitlessloop

7
@chharvey, dari spec w3.org/TR/css-flexbox-1/#item-margins , "Margin item fleksibel yang berdekatan tidak runtuh."
romellem

197

Ini bukan hack. Teknik yang sama juga digunakan oleh bootstrap dan grid-nya, meskipun, bukannya margin, bootstrap menggunakan padding untuk cols-nya.

.row {
  margin:0 -15px;
}
.col-xx-xx {
  padding:0 15px;
}

1
Satu-satunya masalah dengan metode ini adalah mempertahankan item dengan ketinggian yang sama dengan warna latar belakang. Penentuan posisi absolut dengan height:100%; width:100%mengabaikan bantalan item.
Steven Vachon

3
Masalahnya di sini adalah dengan nilai IE10 dan 11. flex-basistidak diperhitungkan box-sizing: border-box, sehingga anak dengan bantalan atau batas apa pun akan melimpahi induknya (atau membungkus dalam kasus ini). Sumber
Carson

18
Ada masalah lain dengan pendekatan ini: menyesuaikan margin seperti ini dapat memperluas lebar halaman. Demo: jsfiddle.net/a97tatf6/1
Nathan Osman

4
Meskipun saya setuju ini bukan peretasan, fakta bahwa sesuatu banyak digunakan tidak berarti itu bukan peretasan. Lihat polyfill, tambalan keamanan sementara, pengeditan hex, dll.
William

15
Tentu saja ini adalah hack. Karena Bootstrap menggunakan metode ini tidak berarti itu bukan peretasan. Ini berarti bahwa Bootstrap menggunakan peretasan.
Michael Benjamin

108

Flexbox dan css calc dengan dukungan beberapa baris

Halo, di bawah ini adalah solusi kerja saya untuk semua browser yang mendukung flexbox. Tidak ada margin negatif.

Demo biola

   
.flexbox {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
}

.flexbox > div {
  /*
    1/3  - 3 columns per row
    10px - spacing between columns 
  */
  box-sizing: border-box;
  margin: 10px 10px 0 0;
  outline: 1px dotted red;
  width: calc(1/3*100% - (1 - 1/3)*10px);
}

/*
  align last row columns to the left
  3n - 3 columns per row
*/
.flexbox > div:nth-child(3n) {
  margin-right: 0;
}

.flexbox::after {
  content: '';
  flex: auto;
}

/*
  remove top margin from first row
  -n+3 - 3 columns per row 
*/
.flexbox > div:nth-child(-n+3) {
  margin-top: 0;
}
<div class="flexbox">
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
</div>

Perhatikan kode ini bisa lebih pendek menggunakan SASS

Perbarui 2020.II.11 Kolom selaras di baris terakhir ke kiri

Perbarui 2020.II.14 Margin-bottom dihapus di baris terakhir


13
Saya suka solusi ini tetapi gagal jika hanya ada 2 item di baris terakhir. Item tidak ditumpuk karena justify-content.
James Brantly

4
untuk memperbaiki masalah dua item, ubah saja ke justify-content: space-evenly;atau justify-content: space-around;.
Paul Rooney

6
@ PaulRooney Di situs dengan beberapa daftar, Anda mungkin tidak selalu tahu jumlah item, jika daftar tersebut dihasilkan oleh CMS.
NinjaFart

1
@ 1.21 gigawatt Tolong jangan membuat perubahan sewenang-wenang pada kode / jawaban orang lain; tulis jawaban Anda sendiri.
TylerH

2
@ TylerH Itu tidak sewenang-wenang. Pertanyaannya bertanya bagaimana, "... untuk mengatur jarak antara item-item flexbox". Jawaban ini tidak menunjukkan ukuran selokan. Mengatur warna latar belakang menunjukkan selokan. Menambahkan batas menunjukkan ada margin di bawah baris terakhir.
1,21 gigawatt

93

Anda dapat menggunakan batas transparan.

Saya telah merenungkan masalah ini ketika mencoba membangun model grid fleksibel yang dapat mundur ke model tabel + sel-tabel untuk browser yang lebih lama. Dan Borders untuk talang kolom bagi saya merupakan pilihan terbaik yang tepat. yaitu sel-tabel tidak memiliki margin.

misalnya

.column{
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 10px solid transparent;
}

Perhatikan juga bahwa Anda memerlukan min-width: 50px;flexbox. Model fleksibel tidak akan menangani ukuran tetap kecuali Anda melakukannya flex: none;pada elemen anak tertentu yang Anda inginkan sebagai tetap dan karena itu tidak disertakan "flexi". http://jsfiddle.net/GLpUp/4/ Tetapi semua kolom bersama dengan flex:none;tidak lagi menjadi model fleksibel. Berikut adalah sesuatu yang lebih dekat dengan model fleksibel: http://jsfiddle.net/GLpUp/5/

Jadi Anda benar-benar dapat menggunakan margin secara normal jika Anda tidak membutuhkan fallback sel tabel untuk browser lama. http://jsfiddle.net/GLpUp/3/

Pengaturan background-clip: padding-box;akan diperlukan saat menggunakan latar belakang, karena jika tidak latar belakang akan mengalir ke area perbatasan transparan.


5
jawaban yang bagus margin digunakan secara berbeda dalam flexbox (seperti untuk menyerap ruang ekstra) sehingga batas transparan memberikan solusi yang sangat baik untuk elemen spasi yang merata yang dapat membungkus dengan perilaku seperti margin
Eolis

4
kecuali ketika Anda menggunakan warna latar belakang, latar belakang Anda melebihi batas yang Anda inginkan.
ahnbizcad

2
@ ahnbizcad Nah dengan warna latar yang berbeda, Anda bisa menggunakan warna putih atau memadai tergantung pada latar belakang mana.
hexalys

27
@ahnbizcad: Jika Anda tidak memerlukan dukungan IE8, ini adalah solusi yang lebih baik:background-clip: padding-box
Albin

5
Komentar Albin's di sini membutuhkan lebih banyak suara! Ini solusi terbaik. Batas transparan, dikombinasikan dengan klip latar belakang: kotak-padding (dan margin negatif pada wadah, jika diperlukan, untuk pelurusan tepi yang tepat) adalah solusi yang sempurna. IE8 toh tidak mendukung flexbox sehingga kurangnya dukungan untuk klip latar belakang tidak masalah.
Brian

74

Solusi ini akan bekerja untuk semua kasus bahkan jika ada beberapa baris atau sejumlah elemen. Tetapi hitungan bagian harus sama dengan yang Anda inginkan 4 di baris pertama dan 3 adalah baris kedua tidak akan berfungsi dengan cara itu ruang untuk konten ke-4 akan kosong, wadah tidak akan mengisi.

Kami menggunakan display: grid; dan sifat-sifatnya.

#box {
  display: grid;
  width: 100px;
  grid-gap: 5px;
  /* Space between items */
  grid-template-columns: 1fr 1fr 1fr 1fr;
  /* Decide the number of columns and size */
}

.item {
  background: gray;
  width: 100%;
  /* width is not necessary only added this to understand that width works as 100% to the grid template allocated space **DEFAULT WIDTH WILL BE 100%** */
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Kelemahan dari metode ini adalah di Mobile Opera Mini tidak akan didukung dan di PC ini hanya berfungsi setelah IE10 .

Catatan untuk kompatibilitas browser lengkap termasuk IE11 silakan gunakan Autoprefixer


JAWABAN TUA

Jangan menganggapnya sebagai solusi lama, itu masih salah satu yang terbaik jika Anda hanya ingin satu baris elemen dan itu akan bekerja dengan semua browser.

Metode ini digunakan oleh kombinasi saudara CSS , sehingga Anda dapat memanipulasinya dengan banyak cara lain juga, tetapi jika kombinasi Anda salah, itu dapat menyebabkan masalah juga.

.item+.item{
  margin-left: 5px;
}

Kode di bawah ini akan melakukan triknya. Dalam metode ini, tidak perlu memberi margin: 0 -5px;kepada #boxpembungkus.

Sampel yang berfungsi untuk Anda:

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 22px;
  height: 50px;
}
.item+.item{
 margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>


Saya telah mengedit jawaban berbasis kisi Anda untuk menunjukkan bahwa ia berfungsi dengan benar, walaupun baris terakhir memiliki lebih sedikit item. Untuk membuktikannya bekerja dalam kasus itu. (Jangan ragu untuk kembali jika Anda tidak menyukai perubahan ini.)
ToolmakerSteve

Sesuai pertanyaan ini, mereka hanya diminta untuk mengisi ruang dengan benar dengan elemen anak tanpa retasan, bahwa apa yang saya lakukan, menggunakan kisi yang dapat kita kelola sesuai dengan yang grid-template-columnskita tentukan tidak secara dinamis. Jadi jika Anda memberi nilai untuk 1fr 1fr 1fr 1fritu akan membagi div menjadi 4fractionsdan mencoba untuk mengisi elemen anak di masing-masing fractions, setahu saya itulah satu-satunya cara grid. Apa yang telah saya nyatakan dalam jawaban adalah bahwa jika pengguna perlu membagi div menjadi 4 dan menggunakannya dengan banyak elemen bahkan untuk beberapa baris, gidakan membantu.
weBBer

69

Anda dapat menggunakan & > * + *sebagai pemilih untuk meniru flex-gap(untuk satu baris):

#box { display: flex; width: 230px; outline: 1px solid blue; }
.item { background: gray; width: 50px; height: 100px; }

/* ----- Flexbox gap: ----- */

#box > * + * {
  margin-left: 10px;
}
<div id='box'>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
</div>

Jika Anda perlu mendukung pembungkus fleksibel , Anda dapat menggunakan elemen pembungkus:

.flex { display: flex; flex-wrap: wrap;  }
.box { background: gray; height: 100px; min-width: 100px; flex: auto; }
.flex-wrapper {outline: 1px solid red; }

/* ----- Flex gap 10px: ----- */

.flex > * {
  margin: 5px;
}
.flex {
  margin: -5px;
}
.flex-wrapper {
  width: 400px; /* optional */
  overflow: hidden; /* optional */
}
<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
  </div>
</div>


3
Solusi bersih. Bekerja untuk sejumlah elemen anak fleksibel.
Konrad Gałęzowski

1
Ini adalah apa yang saya cari dan bekerja sangat baik untuk saya
Paul

Satu hal yang perlu diperhatikan adalah bahwa *operator tidak meningkatkan spesifisitas seperti yang Anda harapkan. Jadi tergantung pada css Anda yang ada, Anda mungkin perlu meningkatkan spesifisitas pada .flex > *pemilih atau menambah !importantaturan jika ada pemilih lain yang menerapkan margin pada elemen itu.
Paul Odeon

Solusi terbaik 👍
o01

26

Katakanlah jika Anda ingin mengatur 10pxruang di antara item, Anda bisa mengatur .item {margin-right:10px;}untuk semua, dan mengatur ulang item yang terakhir.item:last-child {margin-right:0;}

Anda juga dapat menggunakan saudara umum ~atau +pemilih saudara berikutnya untuk menetapkan margin kiri pada item tidak termasuk yang pertama .item ~ .item {margin-left:10px;}atau digunakan.item:not(:last-child) {margin-right: 10px;}

Flexbox sangat pintar sehingga secara otomatis menghitung ulang dan mendistribusikan grid secara merata.

body {
  margin: 0;
}

.container {
  display: flex;
}

.item {
  flex: 1;
  background: gray;
  height: 50px;
}

.item:not(:last-child) {
  margin-right: 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Jika Anda ingin mengizinkan bungkus fleksibel , lihat contoh berikut.

body {
  margin: 0;
}

.container {
  display: flex;
  flex-wrap: wrap;
  margin-left: -10px;
}

.item {
  flex: 0 0 calc(50% - 10px);
  background: gray;
  height: 50px;
  margin: 0 0 10px 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>


6
Ini tidak akan berhasil jika barang-barang dibungkus, karena :last-childtidak memengaruhi setiap anak terakhir di akhir baris, benar?
Flimm

2
@ Flimm Saya menambahkan pendekatan untuk bekerja dengan bungkus fleksibel, lihat bagian kedua di atas.
Stiker

Jawaban terbaik untuk saya ... sederhana, bersih, efisien! Bekerja dengan sempurna dengan bungkus fleksibel, terima kasih
Matthieu Marcé

16

Saya telah menemukan solusi yang didasarkan pada pemilih saudara umum ~,, dan memungkinkan bersarang tanpa batas.

Lihat pena kode ini untuk contoh yang berfungsi

Pada dasarnya, di dalam wadah kolom, setiap anak yang didahului oleh anak lain mendapat margin tertinggi. Demikian juga, di dalam setiap wadah baris, setiap anak yang didahului oleh yang lain mendapat margin kiri.

.box {
  display: flex;
  flex-grow: 1;
  flex-shrink: 1;
}

.box.columns {
  flex-direction: row;
}

.box.columns>.box~.box {
  margin-left: 5px;
}

.box.rows {
  flex-direction: column;
}

.box.rows>.box~.box {
  margin-top: 5px;
}
<div class="box columns">
  <div class="box" style="background-color: red;"></div>
  <div class="box rows">
    <div class="box rows">
      <div class="box" style="background-color: blue;"></div>
      <div class="box" style="background-color: orange;"></div>
      <div class="box columns">
        <div class="box" style="background-color: yellow;"></div>
        <div class="box" style="background-color: pink;"></div>
      </div>
    </div>
    <div class="box" style="background-color: green;"></div>
  </div>
</div>


Ini menghasilkan item dengan ukuran berbeda karena margin tidak diterapkan secara global.
Steven Vachon

Anda juga perlu menambahkan beberapa CSS tambahan untuk menangani layar yang lebih kecil karena kelihatannya agak aneh di ponsel, saya akan menerapkan aturan .box ~ .box ke layar yang lebih besar dan untuk layar yang lebih kecil atur kelas .box untuk memiliki lebar max 100% dan margin bawah.
Rhysclay

14

Beranjak dari jawaban sawa, berikut ini adalah versi yang sedikit lebih baik yang memungkinkan Anda untuk mengatur jarak tetap antara item tanpa margin di sekitarnya.

http://jsfiddle.net/chris00/s52wmgtq/49/

Juga termasuk versi Safari "-webkit-flex".

.outer1 {
    background-color: orange;
    padding: 10px;
}

.outer0 {
    background-color: green;
    overflow: hidden;
}

.container
{
    display: flex;
    display: -webkit-flex;
    flex-wrap: wrap;    
    -webkit-flex-wrap: wrap;
    background-color: rgba(0, 0, 255, 0.5);
    margin-left: -10px;
    margin-top: -10px;
}

.item
{
    flex-grow: 1;
    -webkit-flex-grow: 1;
    background-color: rgba(255, 0, 0, 0.5);
    width: 100px;
    padding: 10px;
    margin-left: 10px;
    margin-top: 10px;
    text-align: center;
    color: white;
}

<div class="outer1">
    <div class="outer0">
        <div class="container">
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
        </div>
    </div>
</div>

2
Bukankah ini pada dasarnya sama dengan contoh yang diberikan dalam pertanyaan?
mengarungi


9

Saya telah menggunakan ini untuk kolom lebar yang dibungkus dan diperbaiki. Kuncinya di sini adalahcalc()

Sampel SCSS

$gap: 10px;

dl {
  display: flex;
  flex-wrap: wrap;
  padding: $gap/2;

  dt, dd {
    margin: $gap/2;}

  dt { // full width, acts as header
    flex: 0 0 calc(100% - #{$gap});}

  dd { // default grid: four columns 
    flex: 0 0 calc(25% - #{$gap});}

  .half { // hall width columns
    flex: 0 0 calc(50% - #{$gap});}

}

Sampel Codepen lengkap


2
Ini masih menambahkan selokan sebelum yang pertama dan setelah item terakhir, yang OP mencegah menggunakan margin negatif.
herman

2
Flexbox tidak mendukung calc () di dalam item "flex" di IE 11.
Adam Šipický

Tidak bisa selalu digunakan. bayangkan jika ada juga perbatasan yang diperlukan untuk anak
Andris

9

Sebuah wadah fleksibel dengan -x (negatif) marjin dan item fleksibel dengan x (positif) marjin atau melapisi kedua menyebabkan hasil visual yang diinginkan: Flex item memiliki kesenjangan tetap 2x hanya antara satu sama lain.

Tampaknya hanya masalah preferensi, apakah menggunakan margin atau padding pada item flex.

Dalam contoh ini, item fleksibel diskalakan secara dinamis untuk menjaga celah tetap:

.flex-container { 
  margin: 0 -5px;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.flex-item {
  margin: 0 5px; // Alternatively: padding: 0 5px;
  flex: 1 0 auto;
}

3
Maaf, saya tidak mengerti. Apa yang baru diperkenalkan oleh jawaban Anda yang tidak diucapkan secara langsung dalam pertanyaan?
pengguna

Pertama, saya ingin meringkas bahwa keduanya, margin dan padding pada flex-item mengarah pada hasil yang diinginkan, karena jawaban yang ada hanya menyebutkan satu atau yang lain. Kedua, saya ingin memberi contoh, di mana celah-celah dipertahankan dengan menskalakan item fleksibel itu sendiri.
Tim

inilah contoh codepen yang menunjukkan efek ini. codepen.io/dalgard/pen/Dbnus
pedalpete

8

Akhirnya mereka akan menambahkan gapproperti ke flexbox. Sampai saat itu Anda bisa menggunakan kisi-kisi CSS yang sudah memiliki gapproperti, dan hanya memiliki satu baris. Lebih bagus daripada berurusan dengan margin.


Diskusi di sini: github.com/w3c/csswg-drafts/issues/1696 - mereka juga akan merampingkan penamaan, di seluruh CSS Grid, Flexbox, dan Kolom CSS.
Frank Lämmer

6

CSS gapProperti :

Ada gapproperti CSS baru untuk multi-kolom, flexbox, dan tata letak kotak yang berfungsi di beberapa browser sekarang! (Lihat Dapatkah saya menggunakan tautan 1 ; tautan 2 ).

#box {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  background-color: red;
  gap: 10px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Saat menulis, ini hanya berfungsi di Firefox sedih. Saat ini berfungsi di Chrome jika Anda mengaktifkan "Aktifkan fitur platform web eksperimental" di about:flags.


5

Menggunakan Flexbox dalam solusi saya, saya telah menggunakan justify-contentproperti untuk elemen induk (wadah) dan saya telah menentukan margin di dalam flex-basisproperti item. Periksa cuplikan kode di bawah ini:

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-bottom: 10px;
}

.item {
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #999;
}

.item-1-4 {
  flex-basis: calc(25% - 10px);
}

.item-1-3 {
  flex-basis: calc(33.33333% - 10px);
}

.item-1-2 {
  flex-basis: calc(50% - 10px);
}
<div class="container">
  <div class="item item-1-4">1</div>
  <div class="item item-1-4">2</div>
  <div class="item item-1-4">3</div>
  <div class="item item-1-4">4</div>
</div>
<div class="container">
  <div class="item item-1-3">1</div>
  <div class="item item-1-3">2</div>
  <div class="item item-1-3">3</div>
</div>
<div class="container">
  <div class="item item-1-2">1</div>
  <div class="item item-1-2">2</div>
</div>


5

Dengan flexbox, membuat selokan adalah hal yang menyakitkan, terutama ketika pembungkusnya terlibat.

Anda perlu menggunakan margin negatif ( seperti yang ditunjukkan dalam pertanyaan ):

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}

... atau ubah HTML ( seperti yang ditunjukkan pada jawaban lain ):

<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
            ...
  </div>
</div>

... atau sesuatu yang lain.

Bagaimanapun, Anda memerlukan peretasan yang jelek untuk membuatnya berfungsi karena flexbox tidak menyediakan fitur " flex-gap" ( setidaknya untuk saat ini ).

Masalah talang, bagaimanapun, sederhana dan mudah dengan Layout Grid CSS.

Spesifikasi Grid menyediakan properti yang menciptakan ruang di antara item kotak, sambil mengabaikan ruang antara item dan wadah. Properti-properti ini adalah:

  • grid-column-gap
  • grid-row-gap
  • grid-gap (singkatan untuk kedua properti di atas)

Baru-baru ini, spek telah diperbarui agar sesuai dengan Modul Alignment Kotak CSS , yang menyediakan seperangkat properti penyejajaran untuk digunakan di semua model kotak. Jadi propertinya sekarang:

  • column-gap
  • row-gap
  • gap (steno)

Namun, tidak semua browser yang mendukung Grid mendukung properti yang lebih baru, jadi saya akan menggunakan versi asli dalam demo di bawah ini.

Juga, jika jarak diperlukan antara item dan wadah, paddingpada wadah berfungsi dengan baik (lihat contoh ketiga dalam demo di bawah).

Dari spec:

10.1. Talang: yang row-gap, column-gapdan gap sifat

The row-gapdan column-gapproperti (dan gapsingkatannya), saat ditentukan pada wadah kisi, menentukan talang antara baris kisi dan kolom kisi. Sintaks mereka didefinisikan dalam Kotak CSS Alignment 3 §8 Kesenjangan Antara Kotak .

Efek dari sifat-sifat ini adalah seolah-olah garis grid yang terpengaruh memperoleh ketebalan: jalur kisi antara dua garis kisi adalah ruang antara selokan yang mewakili mereka.

.box {
  display: inline-grid;
  grid-auto-rows: 50px;
  grid-template-columns: repeat(4, 50px);
  border: 1px solid black;
}

.one {
  grid-column-gap: 5px;
}

.two {
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

.three {
  grid-gap: 10px;
  padding: 10px;
}

.item {
  background: lightgray;
}
<div class='box one'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box two'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box three'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Informasi lebih lanjut:


4

Mengapa tidak melakukannya seperti ini:

.item + .item {
    margin-left: 5px;
}

Ini menggunakan pemilih saudara yang berdekatan , untuk memberikan semua .itemelemen, kecuali yang pertama a margin-left. Berkat flexbox, ini bahkan menghasilkan elemen yang sama lebarnya. Ini juga dapat dilakukan dengan elemen-elemen yang diposisikan secara vertikal dan margin-top, tentu saja.


8
Ini akan bekerja selama item flex selalu dalam satu baris. Jika pembungkus diizinkan maka mungkin tidak akan cukup.
Nick F

4

Inilah solusi saya, yang tidak memerlukan pengaturan kelas apa pun pada elemen anak:

.flex-inline-row {
    display: inline-flex;
    flex-direction: row;
}

.flex-inline-row.flex-spacing-4px > :not(:last-child) {
    margin-right: 4px;
}

Pemakaian:

<div class="flex-inline-row flex-spacing-4px">
  <span>Testing</span>
  <span>123</span>
</div>

Teknik yang sama dapat digunakan untuk baris dan kolom flex normal selain contoh inline yang diberikan di atas, dan diperluas dengan kelas untuk spasi selain 4px.


4

Saya sering menggunakan operator + untuk kasus seperti itu

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
.item + .item {
    margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>


3

Saya menemukan cara termudah untuk melakukan ini adalah dengan persentase dan hanya membiarkan margin untuk menghitung lebar Anda

Ini berarti Anda berakhir dengan sesuatu seperti ini jika Anda menggunakan contoh Anda di mana

#box {
   display: flex;
}

.item {
   flex: 1 1 23%;
   margin: 0 1%;
}

Apakah artinya nilai Anda didasarkan pada lebar meskipun yang mungkin tidak baik untuk semua orang.


Baru saja menemukan solusi ini dan ya, itu sangat bagus. Berfungsi dalam kasus saya, setidaknya (pena bagi mereka yang bisa menganggapnya menarik: codepen.io/rishatmuhametshin/pen/XXjpaV ).
rishat

2

Berikut adalah kisi-kisi elemen UI kartu dengan spasi diselesaikan menggunakan kotak fleksibel:

masukkan deskripsi gambar di sini

Saya merasa frustrasi dengan spasi kartu secara manual dengan memanipulasi padding dan margin dengan hasil yang rapuh. Jadi, inilah kombinasi atribut CSS yang saya temukan sangat efektif:

.card-container {
  width: 100%;
  height: 900px;
  overflow-y: scroll;
  max-width: inherit;
  background-color: #ffffff;
  
  /*Here's the relevant flexbox stuff*/
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap; 
}

/*Supplementary styles for .card element*/
.card {
  width: 120px;
  height: 120px;
  background-color: #ffeb3b;
  border-radius: 3px;
  margin: 20px 10px 20px 10px;
}
<section class="card-container">
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
      </section>

Semoga ini bisa membantu orang-orang, sekarang dan masa depan.


Pembaruan: penspasian ini efektif untuk elemen HTML rendering seluler yang membutuhkan perataan tertentu (mis. Tengah, kiri, dll.). Jika Anda menemukan diri Anda menggunakan kotak fleksibel untuk pengembangan ponsel, saya merasa lega dalam beralih ke perataan murni berbasis margin.
buildpax

2

Columnify - Kelas solo untuk N kolom

Flexbox dan SCSS

.columnify {
  display: flex;

  > * {
    flex: 1;

    &:not(:first-child) {
      margin-left: 2rem;
    }
  }
}

Flexbox dan CSS

.columnify {
  display: flex;
}

.columnify > * {
  flex: 1;
}

.columnify > *:not(:first-child) {
  margin-left: 2rem;
}
<div class="columnify">
  <div style="display: inline-block; height: 20px; background-color: blue;"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
</div>

Mainkan dengan itu di JSFiddle .


1

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
/* u mean utility */
.u-gap-10 > *:not(:last-child) {
  margin-right: 10px;
}
<div id='box' class="u-gap-10">
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>


1

Cukup gunakan .item + .itemdalam pemilih untuk mencocokkan dari yang kedua.item

#box {
  display: inline-flex;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 10px;
  height: 50px;
}

#box .item + .item {
  margin-left: 10px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>


1

Asumsi:

  • Anda ingin tata letak kotak 4 kolom dengan pembungkus
  • Jumlah item belum tentu kelipatan 4

Tetapkan margin kiri pada setiap item kecuali item ke-1, ke-5, ke-9 dan seterusnya; dan atur lebar tetap pada setiap item. Jika margin kiri adalah 10px maka setiap baris akan memiliki margin 30px antara 4 item, persentase lebar item dapat dihitung sebagai berikut:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

Ini adalah solusi yang layak untuk masalah yang melibatkan baris terakhir dari flexbox.

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>


1

Memang ada cara yang bagus, rapi, hanya CSS untuk melakukan ini (yang dapat dianggap "lebih baik").

Dari semua jawaban yang diposting di sini, saya hanya menemukan satu yang menggunakan calc () berhasil (oleh Dariusz Sikorski). Tetapi ketika diajukan dengan: "tetapi gagal jika hanya ada 2 item di baris terakhir" tidak ada solusi yang diperluas.

Solusi ini menjawab pertanyaan OP dengan alternatif margin negatif dan mengatasi masalah yang diajukan kepada Dariusz.

catatan:

  • Contoh ini hanya menunjukkan tata letak 3 kolom
  • Ini digunakan calc()untuk membiarkan browser melakukan matematika seperti yang diinginkan - 100%/3 (meskipun 33,3333% harus bekerja dengan baik) , dan (1em/3)*2 (meskipun .66em juga harus bekerja dengan baik) .
  • Ini digunakan ::afteruntuk mengisi baris terakhir jika ada lebih sedikit elemen dari kolom

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}
.flex-container:after {
  content: "";
}
.flex-container > div,
.flex-container:after {
  box-sizing: border-box;
  width: calc((100%/3) - ((1em/3)*2));
}
.flex-container > :nth-child(n + 4) {
  margin-top: 1em;
}

/* the following is just to visualize the items */
.flex-container > div,
.flex-container:after {
  font-size: 2em;
}
.flex-container {
  margin-bottom:4em;
}
.flex-container > div {
  text-align: center;
  background-color: #aaa;
  padding: 1em;
}
.flex-container:after {
  border: 1px dashed red;
}
<h2>Example 1 (2 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
</div>

<h2>Example 2 (3 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>

Juga di https://codepen.io/anon/pen/rqWagE


1

Anda bisa menggunakan properti baru gap. Saya menyalin dan menempelkan penjelasan yang saya temukan di artikel ini , serta informasi lebih lanjut

Layout grid CSS telah memiliki gap (sebelumnya grid-gap) untuk beberapa waktu. Dengan menentukan jarak internal elemen yang mengandung daripada jarak di sekitar elemen anak, gap memecahkan banyak masalah tata letak umum. Misalnya, dengan celah, Anda tidak perlu khawatir tentang margin pada elemen anak yang menyebabkan ruang kosong yang tidak diinginkan di sekitar tepi elemen yang mengandung:

Sayangnya saat ini, hanya FireFox yang mendukung celah dalam tata letak fleksibel.

@use postcss-preset-env {
  stage: 0;
  browsers: last 2 versions
}

section {
  width: 30vw;
  
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(12ch, 1fr));
  
  &[flex] {
    display: flex;
    flex-wrap: wrap;
  }
  
  margin-bottom: 3rem;
}

.tag {
  color: white;
  background: hsl(265 100% 47%);
  padding: .5rem 1rem;
  border-radius: 1rem;
}

button {
  display: inline-flex;
  place-items: center;
  gap: .5rem;
  background: hsl(265 100% 47%);
  border: 1px solid hsl(265 100% 67%);
  color: white;
  padding: 1rem 2rem;
  border-radius: 1rem;
  font-size: 1.25rem;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
<section>
  <h1>Grid</h1> 
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>
<br>
<section flex>
  <h1>Flex</h1>
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>


gapsudah direkomendasikan dalam jawaban di sini stackoverflow.com/a/58041749/2756409 Juga, ini bukan CSS.
TylerH

0

Ini tidak akan berfungsi dalam setiap kasus tetapi jika Anda memiliki lebar anak fleksibel (%) dan mengetahui jumlah item per baris, Anda dapat dengan sangat jelas menentukan margin elemen yang diperlukan dengan menggunakan nth-childpemilih / s.

Ini sangat tergantung pada apa yang Anda maksud dengan "lebih baik". Dengan cara ini tidak memerlukan markup pembungkus tambahan untuk elemen anak atau elemen negatif - tetapi kedua hal tersebut memiliki tempatnya masing-masing.

section {
  display: block
  width: 100vw;
}
.container {
  align-content: flex-start;
  align-items: stretch;
  background-color: #ccc;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  width: 100%;
}

.child-item {
  background-color: #c00;
  margin-bottom: 2%;
  min-height: 5em;
  width: 32%;
}

.child-item:nth-child(3n-1) {
  margin-left: 2%;
  margin-right: 2%;
}
<html>
  <body>
      <div class="container">
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
      </div>
   </body>
</html>


Tidak responsif. Hanya berfungsi untuk induk dengan lebar tetap.
Hijau

1
OP tidak meminta solusi responsif dan contohnya menggunakan lebar fix. Mengingat bahwa ini menggunakan nilai%, mudah untuk berpendapat bahwa ini responsif karena item akan beradaptasi dengan ukuran induk yang ditetapkan berdasarkan persentase.
jnmrobinson

0

Saya menemukan masalah yang sama sebelumnya, lalu menemukan jawaban untuk ini. Semoga ini akan membantu orang lain untuk referensi di masa mendatang.

jawaban panjang pendek, tambahkan batas pada item fleksibel anak Anda. maka Anda dapat menentukan margin antara item-fleksibel untuk apa pun yang Anda suka. Dalam cuplikan, saya menggunakan hitam untuk tujuan ilustrasi, Anda dapat menggunakan 'transparan' jika mau.

#box {
  display: flex;
  width: 100px;
  /* margin: 0 -5px; *remove this*/
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  /* margin: 0 5px; *remove this*/
  border: 1px solid black; /* add this */
}
.item.special{ margin: 0 10px; }
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item special'></div>
</div>


0

Trik margin negatif pada kotak kontainer bekerja sangat baik. Berikut adalah contoh lain yang bekerja sangat baik dengan pesanan, pembungkus dan apa yang tidak.

.container {
   border: 1px solid green;
   width: 200px;
   display: inline-block;
}

#box {
  display: flex;
  flex-wrap: wrap-reverse;
  margin: -10px;
  border: 1px solid red;
}
.item {
  flex: 1 1 auto;
  order: 1;
  background: gray;
  width: 50px;
  height: 50px;
  margin: 10px;
  border: 1px solid blue;
}
.first {
  order: 0;
}
<div class=container>
<div id='box'>
  <div class='item'>1</div>
  <div class='item'>2</div>
  <div class='item first'>3*</div>
  <div class='item'>4</div>
  <div class='item'>5</div>
</div>
</div>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.