Modo migliore per impostare la distanza tra gli oggetti flexbox


781

Per impostare la distanza minima tra gli elementi Flexbox sto usando margin: 0 5pxsu .iteme margin: 0 -5pxsul contenitore. Per me sembra un trucco, ma non riesco a trovare un modo migliore per farlo.

Esempio

#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
Non è un trucco: è uno dei metodi previsti per allineare gli oggetti. Ci sono altre proprietà però. Vedi w3.org/TR/css3-flexbox/#alignment
BoltClock

4
Sì, ho capito. Ma per esempio c'è una proprietà gap di colonna che ci dà la possibilità di controllare la distanza dal container: w3.org/TR/css3-multicol/#column-gap
Sasha Koss

Di causa è un collasso del margine del flexbox. L'altra domanda ha il diritto più stupido di [Come posso fermare il collasso dell'ultimo margine nel flexbox? ] ( stackoverflow.com/questions/38993170/… )
Jack Yang

6
Il modulo CSS Alignment Box Level 3 include una sezione sugli spazi tra le scatole , che si applica agli elementi multi-colonna, ai contenitori flessibili e ai contenitori della griglia. Quindi alla fine questo sarà semplice come: row-gap: 5px- fatto.
Danield,

2
@JohnCarrell firefox in realtà supporta già la gapproprietà su contenitori flessibili ( caniuse )
Danield

Risposte:


428
  • Flexbox non ha margini di collasso.
  • Flexbox non ha nulla di simile border-spacingper le tabelle (tranne per la proprietà CSS gapche non è ben supportata nella maggior parte dei browser, caniuse )

Pertanto, raggiungere ciò che stai chiedendo è un po 'più difficile.

Nella mia esperienza, il modo "più pulito" che non usa :first-child/ :last-childe funziona senza alcuna modifica flex-wrap:wrapè di impostare padding:5pxsul contenitore e margin:5pxsui bambini. Ciò produrrà un 10pxdivario tra ogni bambino e tra ogni bambino e il loro genitore.

dimostrazione

.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
Questo non compie la stessa cosa della domanda, avrai un rientro di 10px all'estrema sinistra e destra, che presumo non abbiano intenzione di avere. Quindi, i margini negativi nella domanda originale.
Chris Nicola,

17
Che dire se la orderproprietà impostata? :first-child/:last-childnon funzionerà come previsto.
Guria,

4
"Flexbox non ha margini di collasso." Molto perspicace e apparentemente vero, ma posso chiedere una citazione?
Chharvey,

2
Non è una risposta peggiore della domanda originale? Questo metodo richiede che si disponga di spazio attorno al contenitore e che la grondaia debba essere sempre un numero pari.
limitlessloop,

7
@chharvey, dalla specifica w3.org/TR/css-flexbox-1/#item-margins , "I margini degli oggetti flex adiacenti non collassano."
Romellem,

197

Questo non è un trucco. La stessa tecnica viene utilizzata anche da bootstrap e dalla sua griglia, sebbene, invece di margine, bootstrap utilizzi il riempimento per i suoi caratteri.

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

1
L'unico problema con questo metodo è mantenere gli oggetti di uguale altezza con i colori di sfondo. Il posizionamento assoluto con height:100%; width:100%ignora l'imbottitura dell'articolo.
Steven Vachon,

3
Il problema qui è con IE10 e 11. i flex-basisvalori non tengono conto box-sizing: border-box, quindi un bambino con qualsiasi imbottitura o bordo traboccerà il genitore (o avvolgerà in questo caso). Fonte
Carson,

18
C'è un altro problema con questo approccio: regolare il margine in questo modo può espandere la larghezza della pagina. Demo: jsfiddle.net/a97tatf6/1
Nathan Osman

4
Anche se sono d'accordo che questo non è un trucco, il fatto che qualcosa sia ampiamente usato non significa che non sia un trucco. Vedi polyfill, patch di sicurezza temporanee, editing esadecimale, ecc.
William

15
Naturalmente questo è un trucco. Poiché Bootstrap utilizza questo metodo non significa che non sia un hack. Significa solo che Bootstrap usa un hack.
Michael Benjamin,

108

Flexbox e css calc con supporto per più file

Ciao, di seguito è la mia soluzione di lavoro per tutti i browser che supportano flexbox. Nessun margine negativo.

Demo di violino

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

Prendi nota che questo codice può essere più breve usando SASS

Aggiornamento 2020.II.11 Colonne allineate sull'ultima riga a sinistra

Aggiornamento 2020.II.14 Rimosso il margine inferiore nell'ultima riga


13
Mi piace questa soluzione, ma fallisce se ci sono solo 2 elementi nell'ultima riga. Gli oggetti non sono impilati insieme a causa di justify-content.
James Brantly,

4
per risolvere il problema dei due elementi basta cambiare in justify-content: space-evenly;o justify-content: space-around;.
Paul Rooney,

6
@PaulRooney Sul sito con più elenchi potresti non conoscere sempre il numero di elementi, se gli elenchi sono generati da un CMS.
NinjaFart

1
@ 1.21gigawatts Non apportare modifiche arbitrarie al codice / risposta di qualcun altro; scrivi invece la tua risposta.
TylerH,

2
@TylerH Non è stato arbitrario. La domanda si chiedeva come, "... per impostare la distanza tra gli oggetti flexbox". Questa risposta non mostra le dimensioni della grondaia. L'impostazione di un colore di sfondo mostra la grondaia. L'aggiunta di un bordo mostra che c'è margine sotto l'ultima riga.
1,21 gigawatt

93

Puoi usare bordi trasparenti.

Ho riflettuto su questo problema mentre cercavo di costruire un modello a griglia flessibile che può ricadere su un modello di tabelle + celle per i browser più vecchi. E i bordi per le grondaie mi sembravano la scelta migliore. cioè le celle della tabella non hanno margini.

per esempio

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

Si noti inoltre che è necessario min-width: 50px;per Flexbox. Il modello flessibile non gestirà dimensioni fisse a meno che non lo facciate flex: none;sul particolare elemento figlio che desiderate fisso e quindi escluso dall'essere "flexi". http://jsfiddle.net/GLpUp/4/ Ma tutte le colonne insieme flex:none;non sono più un modello flessibile. Ecco qualcosa di più vicino a un modello flessibile: http://jsfiddle.net/GLpUp/5/

Quindi puoi effettivamente utilizzare i margini normalmente se non hai bisogno del fallback a celle di tabella per i browser più vecchi. http://jsfiddle.net/GLpUp/3/

L'impostazione background-clip: padding-box;sarà necessaria quando si utilizza uno sfondo, altrimenti lo sfondo scorrerà nell'area del bordo trasparente.


5
Bella risposta. i margini vengono utilizzati in modo diverso nei flexbox (come per assorbire spazio extra), quindi i bordi trasparenti offrono una soluzione eccellente agli elementi equidistanti che possono avvolgere con un comportamento simile al margine
Eolis

4
tranne quando si utilizza il colore di sfondo, lo sfondo supera i limiti desiderati.
ahnbizcad,

2
@ahnbizcad Bene con diversi colori di sfondo, puoi usare il bianco o il colore adeguato a seconda del modo in cui lo sfondo.
hexalys,

27
@ahnbizcad: se non hai bisogno del supporto IE8, questa è una soluzione migliore:background-clip: padding-box
Albin,

5
Il commento di Albin qui ha bisogno di più voti! Questa è la soluzione migliore Bordi trasparenti, in combinazione con clip di sfondo: padding-box (e margini negativi sul contenitore, se necessario, per un corretto allineamento dei bordi) è una soluzione perfetta. IE8 non supporta comunque la flexbox, quindi la sua mancanza di supporto per la clip di sfondo non dovrebbe importare.
Brian,

74

Questa soluzione funzionerà per tutti i casi anche se sono presenti più righe o un numero qualsiasi di elementi. Ma il conteggio della sezione dovrebbe essere lo stesso che vuoi 4 nella prima riga e 3 nella seconda riga non funzionerà in questo modo lo spazio per il 4 ° contenuto sarà vuoto, il contenitore non riempirà.

Stiamo usando display: grid; e le sue proprietà.

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

Il rovescio della medaglia di questo metodo è in Mobile Opera Mini non sarà supportato e su PC funziona solo dopo IE10 .

Nota per la completa compatibilità del browser, incluso IE11, utilizzare Autoprefixer


VECCHIA RISPOSTA

Non pensarlo come una vecchia soluzione, è ancora uno dei migliori se vuoi solo una riga di elementi e funzionerà con tutti i browser.

Questo metodo viene utilizzato dalla combinazione di fratelli CSS , quindi puoi manipolarlo in molti altri modi, ma se la tua combinazione è sbagliata potrebbe anche causare problemi.

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

Il codice qui sotto farà il trucco. In questo metodo, non è necessario dare margin: 0 -5px;al #boxwrapper.

Un campione funzionante per te:

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


Ho modificato la tua risposta basata sulla griglia per dimostrare che funziona correttamente, anche se l'ultima riga contiene meno elementi. Per dimostrare che funziona in quel caso. (Sentiti libero di tornare se non ti piace questo cambiamento.)
ToolmakerSteve

Secondo questa domanda hanno solo chiesto di riempire correttamente lo spazio con gli elementi figlio senza un hack, che ciò che ho fatto, usando la griglia, possiamo gestire secondo la grid-template-columnsdefinizione che non definiamo dinamicamente. Quindi se dai il valore a 1fr 1fr 1fr 1frallora dividerà il div in 4fractionse proverà a riempire gli elementi figlio in ciascuno fractions, a mia conoscenza questo è l'unico modo per entrare grid. Quello che ho affermato nella risposta è che se l'utente ha bisogno di dividere il div in 4 e usarli con molti elementi anche per più file, gidsarà di aiuto.
weBBer

69

Puoi usare & > * + *come selettore per emulare un flex-gap(per una singola riga):

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

Se è necessario supportare il wrapping flessibile , è possibile utilizzare un elemento wrapper:

.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
Soluzione pulita. Funziona con qualsiasi numero di elementi figlio flessibili.
Konrad Gałęzowski il

1
Questo era quello che stavo cercando e ha funzionato alla grande per me 👍
Paul Odeon,

Un punto da notare è che l' *operatore non aumenta la specificità come ci si potrebbe aspettare. Quindi, a seconda del tuo css esistente, potresti dover aumentare la specificità sul .flex > *selettore o aggiungere !importantalla regola se ci sono altri selettori che applicano margine a quell'elemento.
Paul Odeon,

Migliore soluzione 👍
o01

26

Diciamo che se si desidera impostare lo 10pxspazio tra gli elementi, è possibile impostare solo .item {margin-right:10px;}per tutti e ripristinarlo sull'ultimo.item:last-child {margin-right:0;}

Puoi anche usare il fratello maggiore ~o il +selettore di pari livello per impostare il margine sinistro sugli oggetti escluso il primo .item ~ .item {margin-left:10px;}o usare.item:not(:last-child) {margin-right: 10px;}

Flexbox è così intelligente che ricalcola automaticamente e distribuisce equamente la griglia.

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>

Se si desidera consentire l' avvolgimento flessibile , vedere l'esempio seguente.

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
Questo non funzionerebbe se gli articoli fossero incartati, dal momento :last-childche non influisce su tutti gli ultimi figli alla fine di una riga, giusto?
Flimm,

2
@Flimm Ho aggiunto un approccio per lavorare con flex wrap, vedi la seconda parte sopra.
Adesivi

La migliore risposta per me ... semplice, pulito, efficiente! Ha funzionato perfettamente con il bendaggio flessibile, grazie
Matthieu Marcé,

16

Ho trovato una soluzione che si basa sul selettore generale di pari livello ~e consente un annidamento infinito.

Vedi questo codice penna per un esempio funzionante

Fondamentalmente, all'interno dei contenitori delle colonne, ogni figlio preceduto da un altro figlio ottiene un margine superiore. Allo stesso modo, all'interno di ogni contenitore di righe, ogni bambino preceduto da un altro ottiene un margine sinistro.

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


Ciò si traduce in articoli di dimensioni diverse a causa dei margini non applicati a livello globale.
Steven Vachon,

Dovrai anche aggiungere alcuni CSS extra per gestire schermi più piccoli dato che sembra un po 'strano sui dispositivi mobili, applicherei la regola .box ~ .box a schermi più grandi e per schermi più piccoli impostare la classe .box in modo che abbia una larghezza massima del 100% e un margine inferiore.
rhysclay

14

Passando alla risposta di Sawa, ecco una versione leggermente migliorata che ti consente di impostare una spaziatura fissa tra gli elementi senza il margine circostante.

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

È inclusa anche la versione 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
Non è sostanzialmente lo stesso dell'esempio fornito nella domanda?
ford,


9

L'ho usato per colonne con larghezza fissa e fissa. La chiave qui ècalc()

Campione 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});}

}

Campione completo di Codepen


2
Ciò aggiunge ancora una grondaia prima del primo e dopo l'ultimo elemento, che OP impedisce l'uso di margini negativi.
herman,

2
Flexbox non supporta calc () all'interno dell'elemento "flex" in IE 11.
Adam Šipický

Non può essere sempre usato. immagina se ci sono anche confini necessari per i bambini diretti
Andris

9

Un contenitore flessibile con margine -x (negativo) e oggetti flessibili con margine x (positivo) o imbottitura portano entrambi al risultato visivo desiderato: gli oggetti Flex hanno uno spazio fisso di 2x solo tra loro.

Sembra essere semplicemente una questione di preferenza, se usare il margine o l'imbottitura sugli oggetti flessibili.

In questo esempio, gli elementi flessibili vengono ridimensionati dinamicamente per preservare lo spazio fisso:

.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
Scusa, non l'ho capito. Quale novità introduce la tua risposta che non è detta direttamente nella domanda?
utente

In primo luogo, ho voluto riassumere che sia il margine che il riempimento sull'elemento flessibile portano al risultato desiderato, poiché le risposte esistenti menzionano solo l'una o l'altra. In secondo luogo, volevo fare un esempio, in cui i vuoti vengono preservati ridimensionando gli stessi oggetti flessibili.
Tim

ecco un esempio di codepen che mostra questo effetto. codepen.io/dalgard/pen/Dbnus
pedalpete,

8

Alla fine aggiungeranno la gapproprietà a flexbox. Fino ad allora potresti usare invece la griglia CSS che ha già la gapproprietà e avere solo una riga. Più bello che gestire i margini.


Discussione qui: github.com/w3c/csswg-drafts/issues/1696 - inoltre semplificheranno la denominazione, attraverso la griglia CSS, Flexbox e le colonne CSS.
Frank Lämmer,

6

gapProprietà CSS :

Esiste una nuova gapproprietà CSS per layout multi-colonna, flexbox e griglia che ora funziona in alcuni browser! (Vedi Posso usare il collegamento 1 ; collegamento 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>

Al momento della scrittura, questo funziona solo in Firefox purtroppo. Attualmente funziona in Chrome se attivi "Abilita funzionalità della piattaforma web sperimentale" in about:flags.


5

Usando Flexbox nella mia soluzione ho usato la justify-contentproprietà per l'elemento genitore (contenitore) e ho specificato i margini all'interno della flex-basisproprietà degli articoli. Controlla lo snippet di codice qui sotto:

.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

Con la flexbox, la creazione di grondaie è una seccatura, soprattutto quando si tratta di avvolgimento.

Devi utilizzare i margini negativi ( come mostrato nella domanda ):

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

... o modifica l'HTML ( come mostrato in un'altra risposta ):

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

... o qualcos'altro.

In ogni caso, hai bisogno di un brutto hack per farlo funzionare perché flexbox non fornisce una flex-gapfunzione " " ( almeno per ora ).

Il problema delle grondaie, tuttavia, è semplice e facile con CSS Grid Layout.

Le specifiche Grid forniscono proprietà che creano spazio tra gli elementi della griglia, ignorando allo stesso tempo lo spazio tra gli elementi e il contenitore. Queste proprietà sono:

  • grid-column-gap
  • grid-row-gap
  • grid-gap (la scorciatoia per entrambe le proprietà sopra)

Di recente, le specifiche sono state aggiornate per essere conformi al Modulo di allineamento box CSS , che fornisce una serie di proprietà di allineamento da utilizzare in tutti i modelli di box. Quindi le proprietà sono ora:

  • column-gap
  • row-gap
  • gap (abbreviazione)

Tuttavia, non tutti i browser che supportano Grid supportano le proprietà più recenti, quindi userò le versioni originali nella demo di seguito.

Inoltre, se è necessaria una spaziatura tra gli articoli e il contenitore, paddingsul contenitore funziona perfettamente (vedere il terzo esempio nella demo di seguito).

Dalle specifiche:

10.1. Grondaie: i row-gap, column-gape gap proprietà

Le proprietà row-gape column-gap(e la loro gapscorciatoia), quando specificate su un contenitore della griglia, definiscono le grondaie tra le righe della griglia e le colonne della griglia. La loro sintassi è definita in CSS Box Alignment 3 §8 Gaps Between Boxes .

L'effetto di queste proprietà è come se le linee della griglia interessate avessero acquisito spessore: la traccia della griglia tra due linee della griglia è lo spazio tra le grondaie che le rappresentano.

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

Maggiori informazioni:


4

Perché non farlo in questo modo:

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

Questo utilizza il selettore fratello adiacente , per dare tutti gli .itemelementi, tranne il primo a margin-left. Grazie a flexbox, questo si traduce in elementi altrettanto ampi. Questo potrebbe essere fatto anche con elementi posizionati verticalmente e margin-top, ovviamente.


8
Funzionerebbe fino a quando gli oggetti flessibili sono sempre in una singola riga. Se è consentito il wrapping, probabilmente non sarà sufficiente.
Nick F,

4

Ecco la mia soluzione, che non richiede l'impostazione di alcuna classe sugli elementi figlio:

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

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

Uso:

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

La stessa tecnica può essere utilizzata per le normali righe e colonne flessibili in aggiunta all'esempio inline sopra indicato ed estesa con classi per la spaziatura diversa da 4px.


4

Uso spesso l'operatore + per questi casi

#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

Trovo che il modo più semplice per farlo sia con le percentuali e consenta solo al margine di aumentare la tua larghezza

Ciò significa che si finisce con qualcosa del genere se si utilizza l'esempio

#box {
   display: flex;
}

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

Significa che i tuoi valori si basano sulla larghezza, ma ciò potrebbe non essere buono per tutti.


Ho appena trovato questa soluzione e sì, è molto bello. Funziona nel mio caso, almeno (una penna per coloro che potrebbero trovarlo interessante: codepen.io/rishatmuhametshin/pen/XXjpaV ).
Rishat

2

Ecco una griglia di elementi dell'interfaccia utente della scheda con spaziatura completata utilizzando la casella flessibile:

inserisci qui la descrizione dell'immagine

Ero frustrato nel distanziare manualmente le carte manipolando imbottitura e margini con risultati incerti. Ecco quindi le combinazioni di attributi CSS che ho trovato molto efficaci:

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

Spero che questo aiuti le persone, il presente e il futuro.


Aggiornamento: questa spaziatura è efficace per il rendering mobile di elementi HTML che richiedono un certo allineamento (ad es. Centro, sinistra, ecc.). Se ti ritrovi a utilizzare la scatola flessibile per lo sviluppo mobile, ho trovato sollievo nel passaggio all'allineamento basato esclusivamente sui margini.
buildpax,

2

Columnify - Una classe solista per N colonne

Flexbox e SCSS

.columnify {
  display: flex;

  > * {
    flex: 1;

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

Flexbox e 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>

Gioca con esso su 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

Basta usare .item + .itemnel selettore per abbinare dal secondo.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

assumendo:

  • Volete un layout a griglia a 4 colonne con avvolgimento
  • Il numero di articoli non è necessariamente un multiplo di 4

Imposta un margine sinistro su ogni elemento tranne 1, 5, 9 e così via; e imposta la larghezza fissa su ciascun elemento. Se il margine sinistro è 10px, ciascuna riga avrà un margine di 30px tra 4 elementi, la larghezza percentuale dell'articolo può essere calcolata come segue:

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

Questa è una soluzione decente per problemi che riguardano l'ultima fila di 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

C'è davvero un modo carino, ordinato, solo CSS per farlo (che si può considerare "migliore").

Di tutte le risposte pubblicate qui, ne ho trovato solo uno che usa con successo calc () (di Dariusz Sikorski). Ma una volta posato con: "ma non riesce se ci sono solo 2 elementi nell'ultima riga" non c'era soluzione espansa.

Questa soluzione affronta la domanda del PO con un'alternativa ai margini negativi e affronta il problema posto a Dariusz.

Appunti:

  • Questo esempio mostra solo un layout a 3 colonne
  • Utilizza calc()per consentire al browser di eseguire la matematica nel modo desiderato - 100%/3 (sebbene il 33,3333% dovrebbe funzionare altrettanto bene) e (1em/3)*2 (sebbene .66em dovrebbe funzionare anche bene) .
  • Usa ::afterper riempire l'ultima riga se ci sono meno elementi rispetto alle colonne

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

Anche su https://codepen.io/anon/pen/rqWagE


1

È possibile utilizzare la nuova proprietà gap. Copio incolla la spiegazione che ho trovato in questo articolo , così come ulteriori informazioni

Il layout della griglia CSS ha avuto gap (precedentemente gap-gap) per qualche tempo. Specificando la spaziatura interna di un elemento contenitore anziché la spaziatura attorno agli elementi figlio, gap risolve molti problemi di layout comuni. Ad esempio, con gap, non devi preoccuparti dei margini sugli elementi figlio che causano spazi bianchi indesiderati attorno ai bordi di un elemento contenente:

Purtroppo al momento, solo FireFox supporta il gap nei layout flessibili.

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


gapera già stato raccomandato in una risposta qui stackoverflow.com/a/58041749/2756409 Inoltre, questo non è CSS.
TylerH,

0

Non funzionerà in ogni caso, ma se si dispone di larghezze figlio flessibili (%) e si conosce il numero di elementi per riga, è possibile specificare in modo molto pulito i margini degli elementi necessari utilizzando nth-child / i selettore / i.

Dipende in gran parte da cosa intendi per "migliore". In questo modo non è necessario un markup wrapper aggiuntivo per elementi figlio o elementi negativi, ma entrambe le cose hanno il loro posto.

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>


Non reattivo. Funziona solo con parent di larghezza fissa.
Verde

1
L'OP non richiede una soluzione reattiva e il loro esempio utilizza una larghezza fissa. Dato che utilizza i valori%, è facile argomentare che è reattivo poiché gli articoli si adatteranno alle dimensioni del genitore che è impostato in percentuale.
jnmrobinson,

0

Mi sono imbattuto nello stesso problema in precedenza, quindi mi sono imbattuto nella risposta per questo. Spero che possa aiutare gli altri per riferimento futuro.

risposta lunga breve, aggiungi un bordo ai tuoi oggetti flessibili per bambini. quindi puoi specificare i margini tra gli oggetti flessibili a quello che ti piace. Nello snippet, io uso il nero a scopo illustrativo, puoi usare "trasparente" se vuoi.

#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

Il trucco del margine negativo sul contenitore della scatola funziona alla grande. Ecco un altro esempio che funziona alla grande con l'ordine, il wrapping e cosa no.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.