Flexbox: 4 articoli per riga


260

Sto usando una scatola flessibile per visualizzare 8 elementi che verranno ridimensionati dinamicamente con la mia pagina. Come lo costringo a dividere gli elementi in due file? (4 per riga)?

Ecco un colpo rilevante:

(O se preferisci jsfiddle - http://jsfiddle.net/vivmaha/oq6prk1p/2/ )

.parent-wrapper {
  height: 100%;
  width: 100%;
  border: 1px solid black;
}
.parent {
  display: flex;
  font-size: 0;
  flex-wrap: wrap;
  margin: -10px 0 0 -10px;
}
.child {
  display: inline-block;
  background: blue;
  margin: 10px 0 0 10px;
  flex-grow: 1;
  height: 100px;
}
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>


16
[Aggiornamento] Questa domanda si basava su uno scarso design che non rispondeva. Se ti ritrovi a utilizzare una delle risposte seguenti, fai attenzione. In un buon design, avresti più articoli su schermi più grandi e meno su schermi più piccoli. Forzare 4 elementi per tutte le dimensioni dello schermo sembrerà attraente solo su una gamma ristretta di larghezze dello schermo.
Vivek Maharajh,

Risposte:


381

Hai flex-wrap: wrapsul contenitore. Va bene, perché sostituisce il valore predefinito, che è nowrap( sorgente ). Questo è il motivo per cui gli articoli non si avvolgono per formare una griglia in alcuni casi .

In questo caso, il problema principale flex-grow: 1riguarda gli articoli flessibili.

La flex-growproprietà non dimensiona effettivamente gli oggetti flessibili. Il suo compito è distribuire spazio libero nel contenitore ( sorgente ). Quindi, indipendentemente dalle dimensioni dello schermo, ogni elemento riceverà una parte proporzionale dello spazio libero sulla linea.

Più specificamente, ci sono otto articoli flessibili nel tuo contenitore. Con flex-grow: 1, ognuno riceve 1/8 dello spazio libero sulla linea. Dal momento che non ci sono contenuti nei tuoi articoli, questi possono ridursi fino a zero e non andranno mai a capo.

La soluzione è definire una larghezza sugli articoli. Prova questo:

.parent {
  display: flex;
  flex-wrap: wrap;
}

.child {
  flex: 1 0 21%; /* explanation below */
  margin: 5px;
  height: 100px;
  background-color: blue;
}
<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Con flex-grow: 1definito nella flexscorciatoia, non è necessario flex-basisessere del 25%, il che comporterebbe effettivamente tre elementi per riga a causa dei margini.

Dal momento flex-growche consumerà spazio libero sulla riga, flex-basisdeve solo essere abbastanza grande da imporre un involucro. In questo caso, con flex-basis: 21%, c'è molto spazio per i margini, ma mai abbastanza spazio per un quinto elemento.


1
Mi piace perché ha funzionato per me, ma "un sacco di spazio" mi fa sentire un po 'a disagio. C'è qualche piccola finestra o situazione in cui questa "stima" potrebbe fallire?
Jackson,

1
Che tipo di situazione? Nella maggior parte dei layout ci sono casi estremi che possono creare problemi. Tali casi normalmente navigano attraverso analisi costi-benefici perché non si verificano mai o quasi mai. Ad esempio, nella soluzione sopra, se si inseriscono margini molto grandi, il layout potrebbe interrompersi. Se questo è un problema, dovrebbe essere pubblicato nella domanda. @Jackson
Michael Benjamin,

2
"Se inserisci margini molto grandi, il layout potrebbe interrompersi" Questo è un esempio di uno scenario che vorrei evitare. Non mi interessa la praticità; intrattieni la mia adorazione per la perfezione. C'è un modo per essere più esatti?
Jackson,

27
Puoi anche usareflex: 1 0 calc(25% - 10px);
MarkG

2
Bella risposta! Un piccolo miglioramento che uso è margin: 2%;invece di un numero di pixel fisso al fine di impedire alle caselle di saltare a una nuova linea su piccoli dispositivi / risoluzioni. la formula generale è (100 - (4 * box-width-percent)) / 8% per scatole di diverse larghezze
thomaspsk,

104

Aggiungi una larghezza agli .childelementi. Personalmente userei le percentuali sul margin-leftse vuoi averlo sempre 4 per riga.

DEMO

.child {
    display: inline-block;
    background: blue;
    margin: 10px 0 0 2%;
    flex-grow: 1;
    height: 100px;
    width: calc(100% * (1/4) - 10px - 1px);
}

Buona idea. Ho usato questa idea con modifiche minori. jsfiddle.net/vivmaha/oq6prk1p/6
Vivek Maharajh

1
Ah. Questo in realtà non risolve il mio problema. Vedi qui per un esempio: jsfiddle.net/vivmaha/oq6prk1p/7 . Non ho la libertà di usare le percentuali per il mio margine. Devono avere una larghezza fissa. Ciò significa che il magico 23% che abbiamo scelto non funzionerà poiché non tiene conto del margine fisso.
Vivek Maharajh,

3
Sì, calc lo risolve! 'calc (100% * (1/4) - 10px - 1px)'. Vedi jsfiddle.net/vivmaha/oq6prk1p/9
Vivek Maharajh

24
Allora a che serve il flex in questo, ancora?
volte il

Che dire del design reattivo? Non vogliamo dare una larghezza fissa a un bambino
candelabro il

40

Ecco un altro approccio.

Puoi realizzarlo anche in questo modo:

.parent{
  display: flex;
  flex-wrap: wrap;
}

.child{
  width: 25%;
  box-sizing: border-box;
}

Esempio: https://codepen.io/capynet/pen/WOPBBm

E un esempio più completo: https://codepen.io/capynet/pen/JyYaba


1
E se avessi meno di 4 figli? Non mi piace quello spazio vuoto, il bambino non risponde ...
Candelabro

L'altra risposta di Muddasir Abbas utilizza solo le impostazioni di flessibilità, quindi penso che sia una soluzione più pulita.
Andrew Koster,

17

Lo farei così usando i margini negativi e calc per le grondaie:

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

.child {
  width: calc(25% - 10px);
  margin-left: 10px;
  margin-top: 10px;
}

Demo: https://jsfiddle.net/9j2rvom4/


Metodo di griglia CSS alternativo:

.parent {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

Demo: https://jsfiddle.net/jc2utfs3/


14
<style type="text/css">
.parent{
    display: flex;
    flex-wrap: wrap;
}
.parent .child{
    flex: 1 1 25%;
}
</style>    
<div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>

Spero che sia d'aiuto. per maggiori dettagli puoi seguire questo link


4

Credo che questo esempio sia più barebone e più facile da capire rispetto a @dowomenfart.

.child {
    display: inline-block;
    margin: 0 1em;
    flex-grow: 1;
    width: calc(25% - 2em);
}

Ciò esegue gli stessi calcoli della larghezza mentre si taglia direttamente alla carne. La matematica è molto più semplice ed emè il nuovo standard grazie alla sua scalabilità e compatibilità con i dispositivi mobili.


3
em non è davvero il nuovo standard. Può essere una seccatura, e i progettisti non progettano pensando agli EM.
Danny van Holten,

2

.parent-wrapper {
	height: 100%;
	width: 100%;
	border: 1px solid black;
}
	.parent {
	display: flex;
	font-size: 0;
	flex-wrap: wrap;
	margin-right: -10px;
	margin-bottom: -10px;
}
	.child {
	background: blue;
	height: 100px;
	flex-grow: 1;
	flex-shrink: 0;
	flex-basis: calc(25% - 10px);
}
	.child:nth-child(even) {
	margin: 0 10px 10px 10px;
	background-color: lime;
}
	.child:nth-child(odd) {
	background-color: orange; 
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">

	</style>
</head>
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>
</html>

;)


1
Se puoi, per favore, aggiungi qualche contesto sul perché questo risponde alla domanda OP piuttosto che pubblicare semplicemente il codice.
d219

se aggiungi justify-content: space-evenly;al prent, si allineano bene e non devi fare calcil bambino. Grazie per l'esempio, però!
Mattijs,

0

Avvolgimento flessibile + margine negativo

Perché flex vs. display: inline-block?

Perché margine negativo?

O usi SCSS o CSS-in-JS per i casi limite (ovvero il primo elemento nella colonna), oppure imposti un margine predefinito e ti sbarazzi del margine esterno in un secondo momento.

Implementazione

https://codepen.io/zurfyx/pen/BaBWpja

<div class="outerContainer">
    <div class="container">
        <div class="elementContainer">
            <div class="element">
            </div>
        </div>
        ...
    </div>
</div>
:root {
  --columns: 2;
  --betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}

.outerContainer {
    overflow: hidden; /* Hide the negative margin */
}

.container {
    background-color: grey;
    display: flex;
    flex-wrap: wrap;
    margin: calc(-1 * var(--betweenColumns));
}

.elementContainer {
    display: flex; /* To prevent margin collapsing */
    width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
    margin: var(--betweenColumns);
}

.element {
    display: flex;
    border: 1px solid red;
    background-color: yellow;
    width: 100%;
    height: 42px;
}

-12

Ecco un altro modo senza usare calc().

// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
  margin: 0 2% 0 2%;
  width: 21%;
}

// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
  margin: 0 1.66666% 0 1.66666%;
  width: 30%;
}

// and so on!

Questo è tutto quello che c'è da fare. Puoi avere fantasia con le dimensioni per ottenere dimensioni più estetiche, ma questa è l'idea.


6
Non l'ho provato, ma la sintassi CSS è errata (i valori CSS non sono citati e le dichiarazioni dovrebbero finire in punto e virgola), quindi sicuramente non funzionerà nella sua forma attuale.
Nick F,
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.