Avvicinandosi a flexbox, ci si può chiedere se non sia una soluzione conveniente e robusta per tutte le tipologie di layout o solo per alcune. Non c'è una risposta definitiva a questa domanda, tutto andrebbe valutato nella pratica. Di certo flexbox è la soluzione ideale per layout basati su elementi ripetuti che vanno a disporsi su più righe. Si pensi a gallerie di immagini, a pagine con schede di prodotti, a moduli come la Media Library di WordPress, etc. Ciò è vero anche e soprattutto in una prospettiva responsive che guardi all'adattabilità dei contenuti al mobile.
Nella demo 8 abbiamo costruito un layout a griglia con 5 box. Il problema dell'altezza uguale delle colonne lo abbiamo già risolto. Ora vediamo come gestire la disposizione orizzontale e su più righe dei box.
Vogliamo che su desktop (e comunque con uno spazio orizzontale sufficientemente ampio) ogni riga sia occupata da tre box/colonne.
Per l'elemento contenitore .cards-container
abbiamo usato questo codice:
.cards {
display: flex;
display: -webkit-flex;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
align-items: stretch;
-webkit-align-items: stretch;
justify-content: space-between;
-webkit-justify-content: space-between;
margin-top: 10px;
}
Differisce da quanto visto nella sezione precedente solo in un punto, fondamentale. Dato che vogliamo che i box si dispongano su più righe, dobbiamo definire per la proprietà flex-flow
il valore wrap
invece che il default nowrap
.
A questo punto bisogna lavorare sui componenti scheda, i div con classe .card-container
. Ecco il codice:
.card-container {
display: flex;
display: -webkit-flex;
flex-direction: column;
-webkit-flex-direction: column;
flex: 1 1 300px;
-webkit-flex: 1 1 300px;
margin-top: 10px;
padding: 10px;
}
La dichiarazione cruciale è questa:
flex: 1 1 300px;
-webkit-flex: 1 1 300px;
Analizziamola per comprenderne al meglio il funzionamento.
Dichiarando una flex-grow
pari a 1
, facciamo sì che il box diventi flessibile, andando a riempire automaticamente lo spazio disponibile. Visto che per ogni div il valore è uguale, lo spazio disponibile sarò distribuito equamente, salvo piccoli arrotondamenti quando necessario.
Con un valore di 1
per flex-shrink
(il secondo valore) stabiliamo che ogni box può restringersi quando e come necessario.
Infine, la parte più importante. Abbiamo impostato una flex-basis
di 300px. è la dimensione di base del box. Cosa comporta? Torniamo a fare un po' di calcoli secondo la formula già vista in precedenza:
= -
Per noi:
1000px - (dimensione del contenitore)
900px = (somma delle flex-basis)
------
100px (spazio disponibile)
Questi 100px saranno equamente suddivisi tra i box, che infatti (verificate) hanno dimensioni pari a 333px, 334px e 333px.
Questo per la prima riga. Sulla seconda i box sono due, per cui lo spazio disponibile sarà di 400px. Suddiviso equamente fa sì che ciascuno sia largo 500px.
Ma la flex-basis
impostata a 300px è fondamentale anche per gestire il modo in cui i box si adattano a diverse larghezze della viewport. Basta anche qui fare un po' di calcoli.
Se i box hanno una dimensione di base di 300px, se cioè non possono scendere sotto questa dimensione, quando lo spazio in larghezza è inferiore alla loro somma (900px), l'ultimo box 'scende' nella seconda riga per mancanza di spazio, facendo a sua volta scivolare in una terza riga il quinto box (provate a restringere la finestra del browser con la demo aperta).
Quando, ancora, la larghezza della viewport scende sotto i 600px, non essendoci più spazio per due box (300px + 300px), quello a destra scivola in basso, e i cinque box si dispongono uno sull'altro occupando ciascuno una riga.
Sembra complicato, ma una volta compreso il tutto si rimarrà stupiti per la potenza di queste meccanismo. Che ci consente di avere un layout adattabile a varie larghezze senza di fatto ricorrere alle media queries.
Tra l'altro, la soluzione che abbiamo implementato nella demo si rivela perfetta per risolvere un problema che può affliggere questo tipo di griglie, ovvero quelli delle griglie 'sbilanciate' in cui l'ultima riga non presenta lo stesso numero di elementi di quelle soprastanti. Nel nostro esempio, i due elementi della seconda riga si suddividono lo spazio perfettamente, non lasciando vuoti nella griglia.
Sul tema delle griglie sbilanciate e delle soluzioni implementabili se non si adotta il flexbox segnaliamo due fantastici articoli, rispettivamente, di Keith Clark e Heydon Pickering:
Gli spunti sull'uso dei selettori CSS3 tratti da questi contributi sono stati applicati nelle altre demo di questa guida, e ne trovate traccia dando un'occhiata al codice sorgente.
Box senza flex-basis
Per chiudere questa prima parte della sezione dedicata ai layout a griglia, verifichiamo con una controprova il meccanismo della flex-basis
e del wrap delle righe.
Nella demo 9, sui box, invece che
flex: 1 1 300px;
-webkit-flex: 1 1 300px;
abbiamo usato
flex: 1 1 0;
-webkit-flex: 1 1 0;
In questo caso, essendo la dimensione di base pari a 0, non avendo cioè i box una sorta di larghezza minima di riferimento e non essendo specificata altrove la proprietà width
, il meccanismo del wrap non scatta nemmeno, semplicemente perché il browser 'non sa' quando non c'è spazio disponibile. Ogni box occupa una larghezza automatica e uguale.