CSS flexbox: la guida completa, con esempi
Il layout Flexbox (Box Flessibili) è un modo per gestire, allineare e distribuire lo spazio tra elementi contenuti all'interno di un elemento contenitore, anche nei casi in cui la dimensione degli elementi non sia nota a priori, e senza utilizzare delle media query. Flexbox è alla base di Bootstrap, noto framework utilizzato per lo sviluppo di interfacce e template HTML responsive.
Flexbox lavora con due assi:
- l’asse principale: corre in senso orizzontale, da sinistra a destra
- l’asse trasversale: corre in senso verticale dall’alto verso il basso.
Utilizzando questi assi gli elementi possono essere disposti, in relazione tra loro, all’interno del box contenitore. CSS Flexbox assicura che lo spazio tra questi elementi venga riempito in modo adeguato.
Come utilizzare il layout Flexbox
Il layout Flexbox funziona attribuendo ad un elemento contenitore "parent" (generalmente un "div") la capacità di modificare la lunghezza, larghezza o ordine dei suoi elementi "figli" secondo regole precise. Saranno gli elementi "figli" ad essere flessibili.
Ad esempio, possiamo decidere di allinearli da sinistra verso destra, o da destra verso sinistra, o di centrarli nel div contenitore, o di espanderli fino a riempire tutto lo spazio disponibile oppure restringerli in modo tale da prevenire l'overflow, ...
La struttura di un layout Flexbox
Facciamo subito un esempio. Creiamo un file html ("esempio.html") con all'interno il seguente codice.
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body {
background-color:#ffffff;
color:#000000;
}
.container {
background-color: #cccccc;
}
.child {
margin:15px;
padding:50px;
background-color:#ff0000;
text-align: center;
}
</style>
<title>Esempio flexbox</title>
</head>
<body>
<div class="container">
<div class="child" id="box1">Box 1</div>
<div class="child" id="box2">Box 2</div>
<div class="child" id="box3">Box 3</div>
</div>
</body>
</html>
Nell'html il nostro focus sarà sul contenitore "div", con classe "container", che contiene tre "div".
Prova ad testare questa pagina web, e vedrai il risultato: i tre div si presentano uno sotto l'altro
Adesso applichiamo un modello Flexbox a questa struttura aggiungendo la classe "container" a cui assegnamo una proprietà "display" con valore "flex".
.container {
display: flex;
flex-direction: row;
background-color: #cccccc;
}
Riapri la pagina web e vedrai i tre div "figli" affiancati in orizzontale, all'interno del div "contenitore".
Adesso vediamo come trasformare questa struttara in Flebox, attraverso l'utilizzo di una serie di proprietà da applicare al div "container".
flex-direction
Per affiancare questi div in orizzontale, da sinistra verso destra, cioè come indicati nel codice html, si utilizza la proprietà "flex-direction" con valore "row", come indicato nel nostro css, ed è il comportamento di default di una Flexbox, per cui anche omettendolo il risultato sarebbe stato il medesimo.
Se vogliamo affiancarli da destra verso sinistra, quindi ribaltandone l'ordine, utilizziamo il valore "row-reverse". L'ordine sarà quindi inverso rispetto a quello indicato nel codice html.
E' possibile anche allineare i div in verticale, dall'alto verso il basso, con il valore "column"
e dal basso verso l'alto con "column-reverse", per cui il primo elemento è in basso.
Ricapitolando, i possibili valori di flex-direction sono:
- row: da sinistra verso destra (default)
- row-reverse: da destra verso sinistra
- column: dall'altro verso il basso
- column-reverse: dal basso verso l'alto
justify-content
La proprietà "justify-content" serve a definire come allineare gli elementi "child" sull’asse principale del contenitore, cioè sull'asse orizzontale.
Per centrare i 3 elementi utilizziamo il valore center
.container {
display: flex;
flex-direction: row;
background-color: #cccccc;
justify-content:center;
}
Ecco il risultato
Per allineare i "child" sul lato sinistro si utilizza flex-start
Per allineare i "child" sul lato destro si utilizza flex-end
Per distribuire equamente i "child" nel "container", con la stessa spaziatura tra loro, si utilizza space-around
Per distribuire i "child" in modo uniforme, con il primo child posizionato all’inizio del "container" e l’ultimo alla fine del "container", si utilizza space-between
Ricapitolando, i possibili valori di flex-direction sono:
- center: posiziona i child centralmente sull’asse orizzontale, come visto nell'esempio precedente
- flex-start: posiziona i child sul lato sinistro
- flex-end: posiziona i child sul lato destro
- space-around: tutti e tre i child sono distribuiti equamente e con la stessa spaziatura tra uno e l’altro, cioè lo spazio intorno ai child è distribuito in modo uniforme
- space-between: lo spazio tra i child è distribuito in modo uniforme, con il primo child è posizionato all’inizio del "container" e l’ultimo alla fine del "container" cioè sul lato destro
align-items
Mentre proprietà "justify-content" serve a definire come allineare gli elementi "child" sull’asse principale del contenitore, cioè sull'asse orizzontale, "align-content" lavora in modo simile ma sull'asse verticale.
La proprietà "align-items" serve a stabilire come allineare i child sull’asse trasversale del contenitore, quindi in verticale.
Cominciamo con il dare una altezza al div contenitore (400px), inoltre variamo l'altezza dei vari "child", così da capire l'impatto di questo tipo di allineamento, ed utilizziamo la proprietà "align-items" con valore "center" per centrare verticalmente gli elementi "child" rispetto al contenitore
.container {
display: flex;
flex-direction: row;
background-color: #cccccc;
height:400px;
justify-content:center;
align-items: center;
}
#box1{padding:20px 50px;}
#box2{padding:50px 50px;}
#box3{padding:35px 50px;}
Ecco il risultato, in cui evidenziamo la linea rispetto alla quale vengono allineati i "child"
Per posizionare i "child" vicino al lato superiore del "container" utilizziamo flex-start
Per posizionare i "child" vicino al lato inferiore del "container" utilizziamo flex-end
Se vogliamo che i "child" occupino tutta l’altezza del "container" utilizziamo stretch
Se vogliamo che i "child" vengano allineati rispetto alla baseline del loro testo, utilizziamo baseline
Ricapitolando i possibili valori per gestire l’allineamento verticale:
- center: i "child" sono posizionati centralmente sull’asse verticale
- flex-start: i "child" sono posizionati tutti vicino al lato superiore del "container"
- flex-end: i "child" sono posizionati tutti vicino al lato inferiore del "container"
- stretch: i "child" occupano tutta l’altezza del "container"
- baseline: i "child" sono allineati sulla linea di base del testo contenuto in essi
Nota: Se il "container" dispone di un valore "height", allora il valore di default è "flex-start", altrimenti è "stretch".
flex-wrap
Questa proprietà specifica se i "child" devono essere disposti su un’unica riga oppure su più righe.
Per capire questo concetto cambiamo esempio ed aggiungiamo qualche elemento "child" al nostro html:
<div class="container">
<div class="child box1">1</div>
<div class="child box2">2</div>
<div class="child box3">3</div>
<div class="child box4">4</div>
<div class="child box5">5</div>
<div class="child box6">6</div>
</div>
Modifichiamo anche lo stile in questo modo
.container{
background-color: #cccccc;
display:flex;
flex-direction:row;
flex-wrap:wrap;
}
.child{
font-size:25px;
text-align:center;
padding:15px;
width:40%;
}
.box1{background:green;}
.box2{background:blue;}
.box3{background:red;}
.box4{background:magenta;}
.box5{background:yellow;}
.box6{background:pink;}
Normalmente, quando i "child" occupano più dello spazio consentito dalla schermata, quelli in eccesso andranno automaticamente su una nuova riga: con flexbox possiamo cambiare questa regola.
Assegnando, come in questo esempio, a flex-wrap il valore nowrap, gli elementi resteranno sulla stessa riga
Il valore di default è wrap, che manda a capo gli elementi che non stanno sulla riga
Mentre con wrap-reverse, la disposizione degli elementi avviene dal basso verso l'alto
Ricapitolando, i possibili valori della proprietà "flex-wrap" sono:
- nowrap: per non mandare nessun elemento del parent su un’altra riga
- wrap: per mandare a capo gli elementi che non ci stanno sulla stessa riga
- wrap-reverse: la disposizione degli elementi avviene dal basso verso l’alto
NOTA: è possibile utilizzare la proprietà flex-flow come sintesi abbreviata per indicare allo stesso tempo flex-direction e flex-wrap.
align-content
Se il "container" ha "child" disposti su più righe (quando "flex-wrap: wrap"), la proprietà "align-content" definisce l'allineamento di ogni riga del "container". Quindi il focus non è sui "child" ma sulle righe.
Utilizziamo il valore center se vogliamo che tutte le righe si posizionino al centro del contenitore.
Modifichiamo l'esempio precedente, modificando lo stile del "container" in questo modo
.container{
background-color: #cccccc;
display:flex;
height:400px;
flex-wrap:wrap;
align-content:center;
}
Ecco il risultato
Utilizzando il valore flex-start, tutte le righe vengono posizionate all'inizio del "container".
Utilizzando il valore flex-end, le righe vengono posizionate alla fine del "container".
Utilizzando il valore stretch le righe si allungheranno fino a riempire tutto lo spazio rimanente.
Utilizzando il valore space-around le righe avranno la stessa spaziatura (comprese la prima e l'ultima riga).
Infine, utilizzando il valore space-between distribuiamo le righe in modo uniforme con la prima riga posizionata all’inizio del "container" e l’ultima alla fine del "container".
Ricapitolando, align-content può assumere i seguenti valori
- center: tutte le righe si posizionano al centro del "container"
- flex-start: tutte le righe vengono posizionate all'inizio del "container"
- flex-end: le righe vengono posizionate alla fine del "container".
- stretch: le righe si allungheranno fino a riempire tutto lo spazio rimanente.
- space-around: le righe avranno la stessa spaziatura (comprese la prima e l'ultima riga).
- space-between: distribuiamo le righe in modo uniforme con la prima riga posizionata all’inizio del "container" e l’ultima alla fine del "container".
Fino ad adesso abbiamo visto proprietà da applicare al div "container". Adesso passiamo ad alcune proprietà da applicare agli elmenti "child".
order
Con la proprietà order possiamo modificare l'ordine in cui verranno visualizzati i div "child" rispetto al "container" padre.
Ripartiamo da un esempio con quattro "child " in cui vogliamo che il box1 venga visualizzato come secondo elemento, il box 2 come quarto, il box 3 come primo, e il box 4 come terzo:
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Esempio flexbox</title>
<style>
body {
background-color:#ffffff;
color:#000000;
}
.container {
display: flex;
flex-direction: row;
background-color: #cccccc;
}
.child {
margin:15px;
font-size:2em;
background-color:#ff0000;
text-align: center;
}
#box1 {order:2;}
#box2 {order:4;}
#box3 {order:1;}
#box4 {order:3;}
</style>
</head>
<body>
<div class="container">
<div class="child" id="box1">Box 1</div>
<div class="child" id="box2">Box 2</div>
<div class="child" id="box3">Box 3</div>
<div class="child" id="box4">Box 4</div>
</div>
</div>
</body>
</html>
Ecco il risultato
Di default la proprietà order ha valore 0.
flex-grow
Come possiamo vedere nell'esempio precedente, tolti i margini impostati ai vari "child", esiste dello spazio vuoto in eccesso nel "container".
La proprietà flex-grow consente di impostare il fattore di ingrandimento (di crescita) di un elemento "child" rispetto agli altri, in modo da riempire tutto lo spazio in eccesso, ed ammette un valore numerico (non negativo).
Se, ad esempio, vogliamo che il child "box1" abbia un fattore di crescita del doppio rispetto agli altri child, utilizziamo la proprietà flex-grow con valore 2.
#box2 {flex-grow:2;}
Se vogliamo che tutti gli elementi abbiano lo stesso fattore di crescita utilizziamo, per tutti, un flex-grow con valore 1.
#box1{flex-grow:1;}
#box2{flex-grow:1;}
#box3{flex-grow:1;}
#box4{flex-grow:1;}
oppure semplicemente
.child{flex-grow:1;}
Il valore di default è 0
flex-basis
Con flex-grow abbiamo visto come definire un fattore di ingrandimento di un elemento "child" (o più elementi) rispetto agli altri, in modo da riempire tutto lo spazio in eccesso. In questo modo i child si dimensionano in "automatico" .
E' tuttavia possibile impostare manualmente le dimensioni di un "child" utilizzando la proprietà flex-basis. Ad esempio, togliamo il flex-grow a tutti i child ed definiamo che ognuno di essi occupi il 25% dello spazio disponibile nel "container".
.child {
margin:15px;
padding:50px;
background-color:#ff0000;
text-align: center;
flex-basis:25%
}
Questo è il risultato
Si possono indicare valori in percentuale, come nel nostro esempio, oppure un valore numerico.
Vediamo di combinare assieme l'utilizzo di flex-basis e flex-grow. Impostiamo a tutti i child un flex-basis del 20%, ed assegnamo al box2 un flex-grow con valore 2
.child {
margin:15px;
font-size:2em;
background-color:#ff0000;
text-align: center;
flex-basis:20%
}
#box2{flex-grow: 2;}
In questo caso il flex-grow è sì il fattore di crescita rispetto agli altri elementi, ma prendendo come riferimento il valore impostato per la proprietà flex-basis, ed il risultato sarà il seguente
Nota: Il valore di flex-basis default è auto e divide lo spazio tra i vari elementi sulla base della proprietà "flex-grow".
Nota: nel caso in cui è impostato "flex-direction:row", oppure se non è specificato nulla, la lunghezza si riferisce alla larghezza (width), altrimenti se è impostato "flex-direction:column" allora la lunghezza si riferisce all’altezza (height).
flex-shrink
Funziona allo stesso modo di flex-grow ma impostando il fattore di riduzione, e definisce come devono restringersi i "child" quando non c'è abbastanza spazio nel "container". Ammette un valore numerico (non negativo).
Di default il suo valore è 1 e fa si che i child vengano equamente distribuiti nello spazio ("container") disponibile. Il valore di default è 1
Se ad esempio un elemento ha la proprietà flex-shrink impostata a 2 allora verrà ridotto il doppio rispetto a quello con flex-shrink uguale a 1.
Vediamo questo esempio
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Esempio flexbox</title>
<style>
body {
background-color:#ffffff;
color:#000000;
}
.container {
width:100%;
max-width: 960px;
background-color:#cccccc;
font-size: 32px;
display: flex;
flex-direction: row;
}
.child {
width:320px;
text-align:center;
padding:20px;
}
#box1{background-color:red; flex-shrink:1;}
#box2{background-color:blue; flex-shrink:2;}
#box3{background-color:green; flex-shrink:3;}
</style>
</head>
<body>
<div class="container">
<div class="child" id="box1">Box 1</div>
<div class="child" id="box2">Box 2</div>
<div class="child" id="box3">Box 3</div>
</div>
</div>
</body>
</html>
Aprite questo esempio nel vostro browser e poi.... riducete lo schermo e vedrete come i tre box di riducono in modo differente.
flex
Questa proprietà è semplicemente un modo compatto per indicare in un’unica regola i valori per "flex-grow", "flex-shrink" e "flex-basis", dove il secondo e terzo paramtero sono opzionali e i valori default sono 0, 1 e auto.
align-self
Questa proprietà consente di specificare, per un singolo "child" l’allineamento sull’asse trasversale, cioè in verticale. In definitiva questa proprietà sostituisce l’allineamento impostato dalla proprietà "align-items" impostato nel "container", se presente. Ammette i seguenti valori: flex-start, flex-end, center, baseline, stretch.
Ecco un esempio
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
.container {
display: flex;
flex-direction: row;
background-color: #cccccc;
height:400px;
}
.child {
margin:15px;
padding:50px;
background-color:#ff0000;
text-align: center;
font-size:25px;
}
#box1 {align-self: flex-start;}
#box2 {align-self: flex-end;}
#box3 {align-self: center;}
#box4 {align-self: baseline;}
#box5 {align-self: stretch;}
</style>
</head>
<body>
<div class="container">
<div class="child" id="box1">1</div>
<div class="child" id="box2">2</div>
<div class="child" id="box3">3</div>
<div class="child" id="box4">4</div>
<div class="child" id="box5">5</div>
</div>
</body>
</html>
Ecco il risultato
Abbiamo così concluso la lunga spiegazione relativa all'ultizzo di Flexbox. Solo con molta pratica riuscirete ad impadronirvi di questo strumento.