Tra le novità relative ai CSS introdotte con Internet Explorer 11, spicca il supporto completo al modulo CSS3 Flexible Box Layout (più noto, semplicemente, come Flexbox). Il browser di Microsoft aveva introdotto tale supporto già nella versione 10, ma adeguandosi a quella che poi si è rivelata, nel processo verso la specifica definitiva, una bozza intermedia e provvisoria.
Nella nuova release IE si conforma invece pienamente al documento del W3C attualmente allo stato di Candidate Recommendation: tutte le proprietà previste dal modulo sono supportate senza nemmeno la necessità di ricorrere, nella dichiarazione delle proprietà stesse, a prefissi proprietari.
Per gli sviluppatori si tratta di una buona notizia per svariate ragioni. Il modello flexbox, infatti, è da molti considerato lo strumento del futuro rispetto ad un processo fondamentale nel design quale la strutturazione del layout, uno strumento che consentirà di operare in maniera più efficace e meno problematica rispetto alle tecniche, pur valide, via via implementate nel corso degli anni.
Se si considera che nelle stesse settimane in cui è stato presentato Internet Explorer 11 anche Safari, nelle versioni 6.1 e 7.0, ha esteso il supporto alla specifica definitiva, il risultato è che oggi tutti i principali browser nelle loro release più recenti sono in grado di gestire correttamente layout concepiti e realizzati con i box flessibili. Per lo stato dell'arte sul supporto cross-browser basterà verificare le tabelle sempre aggiornate di Can I Use.
Si tenga comunque presente che se si vuole usare il flexbox garantendo la massima retrocompatibilità sarà necessario inserire nel CSS, insieme alle dichiarazioni standard dell'ultima versione della specifica, anche quelle che fanno riferimento alla vecchia sintassi (quella intermedia supportata da IE10 ma anche la prima, supportata, per esempio, da Safari fino alla versione 6).
Nelle demo che accompagnano questo articolo useremo solo la sintassi più recente, per comodità didattica e perché è quella con cui, da sviluppatori, dovremo imparare a prendere confidenza.
Principi di base del flexbox
Con il flexbox, forse per la prima volta nella storia dei CSS, gli sviluppatori hanno a disposizione uno strumento esplicitamente pensato per la strutturazione del layout. Nel tempo, infatti, questo compito è stato demandato in modi spesso ingegnosi a proprietà e funzionalità dei CSS non progettate in prima istanza per il layout: si pensi solo ai float o al posizionamento degli elementi.
Il modulo dei box flessibili ci consente di usare tutta una serie di proprietà con cui possiamo dire definitivamente addio a tali tecniche: la specifica, infatti, è stata pensata per rendere semplice e immediata la gestione di box all'interno di un elemento contenitore e per risolvere problematiche come la centratura degli elementi, la loro disposizione sull'asse orizzontale o su quello verticale, la configurazione e la gestione dello spazio disponibile, il dimensionamento relativo dei box contenuti in un contenitore flessibile, l'indipendenza della posizione degli elementi presenti sulla pagina rispetto al codice sorgente.
Per avere un'idea di alcuni dei classici problemi in tema di layout risolti dal flexbox, è molto utile il progetto Solved by Flexbox. Che si tratti della centratura orizzontale e verticale di elementi, del problema dello sticky footer o del caso del cosiddetto 'Holy Grail Layout', gli esempi presentati mostrano tutti come il flexbox risolva tutte queste problematiche tradizionali di design con i CSS con poche righe di codice e senza hack. Il tutto potendo gestire facilmente il layout in una prospettiva ormai imprescindibile come quella del design responsivo.
A livello tecnico-implementativo, prima di iniziare a usare il flexbox è necessario comprendere alcuni concetti di base. In sintesi sono rappresentati in questa immagine presa direttamente dal documento del W3C.
Il sistema è fondato su due elementi costitutivi:
- un elemento contenitore (flex container): è quello che contiene i box flessibili e viene creato usando il valore
flex
per la proprietàdisplay
; - box flessibili (flex items): sono gli elementi figli dell'elemento contenitore che assumono come loro caratteristica fondamentale quella della 'flessibilità'; su questi box non hanno effetto le proprietà
float
,clear
evertical-align
.
Di fatto, il modello di layout del flexbox prevede in prima istanza la dichiarazione di un elemento contenitore e delle sue proprietà di base, quindi l'impostazione del comportamento dei singoli box al suo interno.
Le tredici proprietà che compongono il modulo possono pertanto essere suddivise in due gruppi: quelle che si applicano al contenitore e quelle che si applicano ai box flessibili.
Rientrano nel primo gruppo:
Proprietà | Valori | Descrizione |
---|---|---|
display: flex | è il valore della proprietà display con cui si imposta un contenitore flessibile; |
|
flex-direction | row | row-reverse | column | column-reverse |
specifica la direzione dell'asse principale (main axis) su cui si dispongono i box flessibili nel contenitore; |
flex-wrap | nowrap | wrap | wrap-reverse |
specifica se i box all'interno del contenitore si dispongono su una riga o su più righe in base allo spazio disponbile; |
flex-flow | è una proprietà a sintassi abbreviata con cui esprimere insieme i valori per flex-direction e flex-wrap ; |
|
justify-content | flex-start | flex-end | center | space-between | space-around |
stabilisce la modalità di allineamento dei box flessibili sull'asse principale del contenitore; |
align-items | stretch | flex-start | flex-end | center | baseline |
gestisce l'allineamento dei box flessibili lungo l'asse perpendicolare (cross axis) all'asse principale; |
align-content | stretch | flex-start | flex-end | center | space-between | space-around |
gestisce l'allineamento di una riga di box flessibili lungo l'asse perpendicolare; ha effetto solo su contenitori multi-riga; |
Le proprietà che si applicano ai box flessibili sono:
Proprietà | Valori | Descrizione |
---|---|---|
order | specifica l'ordine in cui viene mostrato un box rispetto agli altri definiti nel contenitore; | |
align‐self | auto | flex-start | flex-end | center | baseline | stretch |
consente di specificare per un singolo box l'allineamento sull'asse perpendicolare, superando caso per caso le impostazioni definite con la proprietà align-items ; |
flex‐grow | consente di impostare il fattore di ingrandimento di un box rispetto agli altri presenti nel contenitore quando si distribuisce lo spazio disponbile; | |
flex‐shrink | è la proprietà opposta rispetto a flex-grow , dal momento che agisce sul fattore di restringimento relativo tra i box; |
|
flex-basis | consente di specificare la dimensione principale (main size) iniziale (in valori assoluti o in percentuale) di un box; | |
flex | proprietà a sintassi abbreviata per dichiarare in un'unica regola i valori per flex-grow , flex-shrink e flex-basis . |
Per approfondimenti ed esempi di codice, rimandiamo alla documentazione ufficiale di Microsoft. Su MSDN è anche disponibile una pagina che presenta il confronto completo tra la nuova sintassi supportata da Internet Explorer 11 e quella supportata da Internet Explorer 10.
E dal momento che alcuni aspetti teorici della specifica sono invero un po' ostici, specie quando si tratta di valutare in che modo le singole proprietà interagiscono tra di loro, consigliamo anche di usare per vedere messi in pratica i princìpi di base il tool online CSS Flexbox Please realizzato da Eiji Kitamura. Si tratta della migliore palestra per prendere confidenza con questa tecnica tutta nuova partendo dalla pratica.
A questo proposito, nella seconda parte dell'articolo iniziamo ad esaminare alcuni esempi.
Esempi
Prima di concludere, vediamo una semplice dimostrazione pratica.
Creeremo un box contenitore centrato orizzontalmente e verticalmente rispetto al body, con all'interno tre box centrati a loro volta orizzontalmente e verticalmente, disposti in modo da essere equamente distanziati nello spazio disponibile.
Si parte inserendo nel corpo del documento un div
con id container
:
<div id="container">
...
</div>
Assegniamo via CSS a questo div
una serie di stili per lo sfondo, il bordo e le dimensioni:
#container {
background: #e3e3e3;
border: 2px solid black;
width:740px;
height: 300px;
}
Per centrarlo verticalmente e orizzontalmente sulla pagina, dobbiamo tenere presente che il suo elemento contenitore è l'elemento body
. Per prima cosa dobbiamo pertanto fissare l'altezza per i selettori html
e body
al 100%, in modo da creare una dimensione di riferimento per la centratura verticale:
html, body {height: 100%;}
A questo punto, ci affidiamo al flexbox. Basterà impostare per il body
(il nostro contenitore 'flessibile') la proprietà display
sul valore flex
, e quindi agire sulle proprietà justify-content
e align-items
: per entrambe useremo il valore center
. Nel codice si risolve tutto in tre regole, la sintassi è qui più verbosa perché per Safari è ancora necessario ricorrere al prefisso -webkit-
:
body {
margin:0;
padding:0;
display: flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
-webkit-justify-content: center;
-webkit-align-items: center;
}
Ecco cosa abbiamo ottenuto in questo primo step.
È ora il momento di aggiungere i tre box all'interno del div con id container
:
<div id="container">
<div id="box-1">Box 1</div>
<div id="box-2">Box 2</div>
<div id="box-3">Box 3</div>
</div>
Mettiamo mano al CSS per assegnare uno sfondo e un bordo ai tre box:
#box-1 {
background: red;
border: 1px solid black;
}
#box-2 {
background: blue;
border: 1px solid black;
}
#box-3 {
background: green;
border: 1px solid black;
}
A questo punto, volendo usare il flexbox per disporre i tre box, è necessario che diventino 'flessibili'. Per il loro elemento parente, il div con id container
, dobbiamo pertanto dichiarare display: flex
:
#container {
background: #e3e3e3;
border: 2px solid black;
width:740px;
height: 300px;
display: flex;
display: -webkit-flex;
}
Non basta. Dobbiamo anche dichiarare in che direzione disporre i box, ovvero stabilire l'asse principale. Vogliamo che siano disposti su una riga e non in colonna, e così settiamo su row
il valore per la proprietà flex-direction
. Inoltre, vogliamo che il contenitore sia a riga singola: usiamo la proprietà flex-wrap
con il valore nowrap
. Per semplificare, facciamo ricorso alla proprietà flex-flow
per dichiarare entrambe le proprietà con una sola regola:
#container {
background: #e3e3e3;
border: 2px solid black;
width:740px;
height: 300px;
display: flex;
display: -webkit-flex;
flex-flow: row nowrap;
-webkit-flex-flow: row nowrap;
}
Ecco cosa abbiamo ottenuto fino a questo punto.
Per centrare verticalmente i tre box all'interno del contenitore, ricorriamo ancora una volta alla proprietà align-items
:
#container {
background: #e3e3e3;
border: 2px solid black;
width:740px;
height: 300px;
display: flex;
display: -webkit-flex;
flex-flow: row nowrap;
-webkit-flex-flow: row nowrap;
align-items: center;
-webkit-align-items: center;
}
Questo è il risultato.
Il nostro obiettivo però è di avere i tre box distanziati equamente tra di loro e centrati anche orizzontalmente. Usiamo allora la proprietà justify-content
con il valore space-around
. A differenza del valore space-between
, che colloca il primo e l'ultimo box alle estremità del contenitore, space-around
aggiunge un margine verso il bordo del contenitore stesso. Ecco il codice:
#container {
background: #e3e3e3;
border: 2px solid black;
width:740px;
height: 300px;
display: flex;
display: -webkit-flex;
flex-flow: row nowrap;
-webkit-flex-flow: row nowrap;
align-items: center;
-webkit-align-items: center;
justify-content: space-around;
-webkit-justify-content: space-around;
}
Ed ecco l'esito.
A questo punto bisogna gestire il dimensionamento dei box in larghezza e altezza. Si tratta di scelte progettuali che dipendono dal contenuto e dalla configurazione di layout che si vuole ottenere. Si tenga comunque presente che in assenza di un dimensionamento esplicito i box adeguano le loro dimensioni a quelle del contenuto (esempio 5).
Nel nostro esempio ciò che vogliamo ottenere, lo ricordiamo, sono dei box ad altezza e larghezza fissa equamente distanziati. Pertanto, senza ricorrere a particolari proprietà del flexbox, scriviamo nel codice:
#box-1, #box-2, #box-3 {
padding: 20px;
width: 180px;
height: 100px;
}
Questo il risultato.
La flessibilità, in questo scenario, è data dal fatto che i margini sono calcolati automaticamente in base allo spazio disponibile che viene equamente distribuito.
Un'ultima variante prima di concludere. Sfruttiamo la proprietà order
applicata ai box per modificare l'ordine in cui compaiono, superando così l'ordine di dichiarazione nel codice sorgente. Si tratta, come si può intuire, di una funzionalità utilissima i svariati scenari, a partire dal design responsivo. Basta impostare il valore della proprietà con un numero corrispondente alla posizione:
#box-1 {
background: red;
border: 1px solid black;
order: 2;
-webkit-order: 2;
}
#box-2 {
background: blue;
border: 1px solid black;
order: 3;
-webkit-order: 3;
}
#box-3 {
background: green;
border: 1px solid black;
order: 1;
-webkit-order: 1;
}
Ecco il risultato finale.
Conclusioni
Il flexbox è sicuramente destinato a diventare una delle tecniche più usate negli anni a venire per la strutturazione del layout. L'uso in contesti reali, i test, il lavoro degli sviluppatori serviranno ad affinare le conoscenze e a delineare al meglio gli scenari d'uso più adatti. Con una specifica ormai quasi definitiva e un supporto dei browser così esteso dopo l'uscita di Internet Explorer 11 non abbiamo più scuse per rimandare l'approfondimento e lo studio. Flexbox è qui per rimanere.