No. 202

Titolo originale: CSS Floats 101

Pubblicato in: CSS, HTML, Layout & Grids

Scritto da Noah Stokes

La proprietà float è una risorsa molto utile e potente a disposizione dei web designer/developer che lavorano con HTML e CSS. Purtroppo però, può anche causare frustrazione e confusione se non si comprende appieno il suo funzionamento. Inoltre, in passato, il float è stato associato a dei bug dei browser piuttosto seri, quindi è normale essere nervosi quando lo si usa nelle regole del proprio CSS. Ma calmiamoci e liberiamoci dalla frustrazione: vi mostrerò come si comporta la proprietà float applicata agli elementi e quanto sia incredibilmente utile una volta che la si padroneggia.

Nel mondo della stampa vediamo dei float ogniqualvolta leggiamo un articolo in un magazine in cui vi sia un'immagine sulla sinistra o sulla destra con del testo tutto intorno ad essa. Nel mondo di HTML/CSS, il testo “avvolge” un'immagine più o meno come in un layout per magazine solo se a questa viene applicata la proprietà float. Le immagini sono solo uno dei molti casi d'uso per la proprietà float: possiamo ottenere mediante float anche il noto layout a due colonne. In effetti, potete applicare il float praticamente a qualunque elemento nel vostro HTML. Conoscendo e comprendendo le basi della proprietà float, insieme ai fondamenti del posizionamento, sarete in grado di ottenere qualunque layout con sicurezza.

La definizione

Cominciamo dalla definizione di float data dal W3C:

Un float è un elemento che viene spostato a sinistra o a destra sulla riga corrente. La caratteristica più importante di un float (o di un elemento a cui è applicato il float) è che il contenuto può scorrergli lungo il bordo (oppure si può impedire che ciò avvenga utilizzando la proprietà “clear”). Il contenuto scorre lungo il lato destro di un elemento con float impostato a left e lungo il lato sinistro di un elemento con float impostato a right.

Alla proprietà float si possono applicare quattro valori: left, right, inherit e none. Ciascuno di questi valori è auto-esplicativo. Ad esempio, se assegnate float: left ad un elemento, questo si sposterà sul lato più a sinistra del suo elemento padre. La stessa idea si applica a float: right: l'elemento verrà mandato sul lato più a destra del suo elemento padre. Il valore inherit dice all'elemento a cui è applicato di ereditare il valore di float del suo elemento padre. Il valore none è il valore di default e dice all'elemento di non spostarsi sotto l'effetto del float.

Ecco un semplice esempio come quello citato prima del magazine, Esempio A ed il relativo markup:

 
img { 
  float: right;
  margin: 10px;
}

Il comportamento del float

Niente di troppo complesso, ma tutto sommato abbastanza bello, no? Un gioco da ragazzi, mi dite. Ok, ben prima di entrare nella parte in cui i float ci aprono la porta di un mondo popolato da unicorni amanti del bacon, facciamo un attimo retromarcia e parliamo di quello che stiamo effettivamente sperimentando. Nel mondo del web, il nostro HTML deve sottostare ad alcune regole, in particolare al flusso normale. Nel flusso normale, ogni elemento di tipo block (div, p, h1, etc.) si impila sopra l'altro verticalmente, dall'alto della viewport verso il basso. Gli elementi a cui è applicato il float vengono prima disposti in accordo con il flusso normale e poi tolti dal flusso normale e mandati nella parte più a destra o più a sinistra (a seconda del valore applicato) dell'elemento padre. In altre parole, passano dall'essere uno sopra all'altro ad uno di fianco all'altro, purché vi sia spazio sufficiente nell'elemento padre perché ogni elemento a cui è applicato il float vi trovi spazio. Questo comportamento è cruciale e va tenuto a mente quando si creano siti web.

Diamo un'occhiata a qualche altro esempio. Nell'Esempio B, ci sono tre blocchi a cui non è applicata la proprietà float:

 
.block { 
  width: 200px;
  height: 200px;
}

Vedete come si impilano uno sull'altro? Questo è il concetto base di flusso normale. Ecco ora lo stesso esempio con il float applicato agli elementi block, Esempio C:

 
.block { 
  float: left;
  width: 200px;
  height: 200px;
} 

Ora i blocchi sono uno accanto all'altro. Ottimo, abbiamo capito come si fa. Ma cosa succede se non c'è abbastanza spazio nell'elemento padre perché tutti i blocchi stiano uno accanto all'altro? Pensavo non me l'avreste mai chiesto. Prendiamo il nostro ultimo esempio ed aumentiamo il numero di elementi di cinque volte. L'elemento padre in questo esempio è il body del nostro documento. Notate che a seconda della dimensione della finestra del browser (e di conseguenza dell'elemento padre body), i blocchi scendono su una seconda riga, perché non c'è abbastanza spazio per tutti loro per disporsi uno accanto all'altro. Man mano che ridimensionate la finestra del vostro browser per avere più spazio, vedrete i blocchi riposizionarsi. Provateci nell'Esempio D.

Al sicuro

La proprietà float ha un fratellastro, clear. I due si complementano in maniera da rendervi programmatori felici. Come ricorderete, un elemento a cui è applicato il float è prima disposto secondo il flusso normale e poi rimosso da quello. Questo significa che ogni elemento che segue un elemento a cui è applicato il float si comporterà in maniera contraria alle aspettative. Qui è dove sospetto che potremmo cominciare a metterci nei pasticci. Diamo di nuovo un'occhiata ad un rapido esempio con i nostri blocchi: nell'Esempio E, applicherò il float a due blocchi (rosa e azzurro) e subito dopo questi, non applicherò il float agli altri due blocchi (verde ed arancio). Qui di seguito il codice HTML e CSS per l'Example E:

 
<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green"></div>
<div class="block orange"></div>
 
.block {
  width: 200px;
  height: 200px;
}
.float { float: left; }
.pink { background: #ee3e64; }
.blue { background: #44accf; }
.green { background: #b7d84b; }
.orange { background: #E2A741; }

Vi piace il blocco verde? Ma... un attimo! Dov'è il blocco verde? C'è, proprio sotto al blocco rosa. La proprietà float è applicata sia al blocco rosa sia a quello azzurro e si comportano come ci aspetteremmo: posizionandosi uno accanto all'altro. Tuttavia, dal momento che sono stati rimossi dal flusso normale, i blocchi arancio e verde si comportano come se non ci fossero nemmeno: questo è il motivo per cui sotto al nostro blocco rosa è nascosto quello verde. Come rendiamo di nuovo visibile il nostro blocco verde? Utilizzando la proprietà clear.

La proprietà clear ha cinque valori disponibili: left, right, both, inherit e none. Assegnare il valore left vuol dire che il bordo superiore di questo elemento deve stare sotto ogni elemento a cui è applicata la proprietà float: left. Lo stesso concetto si applica per il valore right: l'elemento deve posizionarsi sotto a tutti gli elementi a cui è applicata la proprietà float: right. Utilizzando il valore both si dice all'elemento che il suo bordo superiore deve stare sotto ad ogni elemento a cui è applicata la proprietà left o right. Il valore inherit eredita la proprietà clear dal suo elemento padre, mentre il valore di default none si comporta come ci aspetteremmo. Armati di queste nozioni, prendiamo in considerazione l'Esempio E2. Questa volta applicheremo il clear ai due elementi a cui è applicato il float utilizzando la proprietà clear sul nostro blocco verde. Il nostro codice, leggermente modificato, diventa:

 
<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green clear"></div>
<div class="block orange"></div>
 
.block {
  width: 200px;
  height: 200px;
}
 
.float { float: left; }
.clear { clear: left; }
.pink { background: #ee3e64; }
.blue { background: #44accf; }
.green { background: #b7d84b; }
.orange { background: #E2A741; }

Assegnando il valore clear: left al nostro blocco verde, gli abbiamo detto di comportarsi come se il blocco rosa fosse nel flusso normale del nostro documento (sebbene ne sia stato in realtà rimosso) e di posizionarsi sotto ad esso. Si tratta di una proprietà estremamente potente: come potete vedere, aiuta a portare gli elementi a cui non è applicato un float all'interno del flusso normale, un comportamento che ci aspetteremmo di default. Detto ciò, conoscere e comprendere sia la proprietà float sia clear, apre le porte alla creatività per il vostro HTML e CSS.

Utilizzare i float per i layout

Passiamo ai layout, dove la proprietà float è incredibilmente utile. Possiamo ottenere il classico layout a due colonne in molti modi, molti dei quali usano uno o due elementi a cui si applica float. Diamo un'occhiata ad un semplice esempio: un sito web a due colonne con l'area del contenuto a sinistra, la navigazione a destra ed un'area header e footer a chiuderlo. Per questo articolo, osserveremo solo il codice relativo agli elementi a cui è applicato il float. Ecco l'Esempio F:

 
#container {
  width: 960px;
  margin: 0 auto;
}
 
#content {
  float: left;
  width: 660px;
  background: #fff;
}
 
#navigation {
  float: right;
  width: 300px;
  background: #eee;
}
 
#footer {
  clear: both;
  background: #aaa;
  padding: 10px;
}

Ok, vediamo cosa sta succedendo in questo caso. Il genitore che funge da contenitore qui è chiamato in maniera appropriata #container e tiene a posto gli elementi a cui è applicato il float. Se non ci fosse, gli elementi si sposterebbero sui lati più a sinistra e più a destra della viewport (la finestra del nostro browser). Poi, abbiamo #content e di seguito #navigation. Questi sono i nostri elementi a cui è applicato il float. Abbiamo mandato #content a sinistra e #navigation a destra, per ottenere il layout a due colonne. Ho definito per entrambe una larghezza, così che riempiano l'intero contenitore padre. Infine, abbiamo il #footer, a cui abbiamo assegnato la proprietà clear. Come sappiamo da prima, questa proprietà clear porta gli elementi che si trovano dopo quelli a cui è applicato il float nel flusso normale. In questo caso, al #footer è stato assegnato il valore both, che fa in modo che il #footer si posizioni sotto agli elementi #content e #navigation.

Cosa sarebbe successo se ci fossimo dimenticati di assegnare la proprietà clear al nostro footer? Date un'occhiata all'Esempio G.

Il nostro #footer è scivolato verso l'alto sotto a #navigation. Questo accade perché c'è spazio a sufficienza per ospitare il #footer sotto a #navigation e, dato che lavoriamo all'interno del flusso normale, questo è effettivamente il comportamento corretto. Ma decisamente non è quello che cerchiamo, vero? State cominciando a capire l'interazione tra le proprietà float e clear e in che modo si completano l'una con l'altra.

Se avete il disturbo ossessivo-compulsivo, come me, potreste notare che nell'Esempio F #content e #navigation hanno altezze diverse: ci sono molti modi per gestire questa situazione, ma esulano dallo scopo di questo articolo. Vi suggerisco caldamente di leggere Faux Columns di Dan Cederholm per imparare come fare in modo che le altezze sembrino uguali, indipendentemente dal contenuto.

Prima il float

Fino ad ora abbiamo visto degli esempi piuttosto semplici che non creano troppi mal di testa. Ci sono tuttavia dei gotcha a cui dobbiamo prestare attenzione quando lavoriamo con la proprietà float. Sorprendentemente, uno dei più grossi gotcha non sta nel CSS ma in HTML: il posto in cui inserite l'elemento a cui si applica il float nel HTML può causare risultati differenti. Provate a guardare l'Esempio H.

Qui c'è un piccolo e grazioso quadrato che ha un immagine a cui è applicato un float a destra e del testo attorno a questa. Il nostro CSS è elementare:

 
#container {
  width: 280px;
  margin: 0 auto;
  padding: 10px;
  background: #aaa;
  border: 1px solid #999;
}
 
img {
  float: right;
} 

Il nostro elemento padre, #container ha una larghezza scarsa che mantiene il nostro elemento a cui è applicato il float, l'img, all'interno dei suoi margini. Il nostro HTML sarà così:

 
 
<div id="container">
  <img src="/image.gif" />
  <p>This is some text contained within a 
small-ish box. I'm using it as an example
of how placing your floated elements in different 
orders in your HTML can affect your layouts. For
example, take a look at this great photo 
placeholder that should be sitting on the right.</p>
</div>
 
 

Questo concetto base ci dà il risultato desiderato, ma cosa succederebbe se prendessimo questo stesso esempio e riarrangiassimo leggermente il codice HTML? Nell'Esempio I sposteremo l'img in modo tale che appaia dopo il nostro paragrafo di testo:

 
 
<div id="container">
  <p>This is some text contained within a
small-ish box. I'm using it as an example
of how placing your floated elements in different 
orders in your HTML can affect your layouts. For
example, take a look at this great photo 
placeholder that should be sitting on the right.</p>
  <img src="/image.gif" />
</div>
 
 

Il nostro risultato è meno che desiderabile. La nostra immagine si è spostata a destra, ma non è più nell'angolo in alto a destra dove la volevamo: è finita sotto al nostro paragrafo di testo. Peggio ancora, sembra che esca dal bordo inferiore dell'elemento padre #container. Cosa sta succedendo? Per prima cosa, una regola che ho visto che funziona bene per i miei layout è quella di mettere prima il float. Ossia, nel mio HTML, metto quasi sempre prima nel markup gli elementi a cui devo applicare il float e li metto anche prima di qualsiasi elemento a cui non viene applicato il float ma che interagirà con quelli, come il paragrafo nell'esempio di cui sopra. La maggior parte delle volte, ottengo così il risultato sperato. In secondo luogo, la ragione per cui l'immagine sembra che stia a cavallo del bordo inferiore dell'elemento #container ha a che fare con una cosa chiamata “collapsing”. Vediamo che cosa è il collapsing e come possiamo gestirlo al meglio.

Collapsing

Il collapsing avviene quando un elemento padre che contiene un numero qualsiasi di elementi a cui è applicato il float non si espande fino a contenerli interamente, come farebbe se agli elementi non fosse applicato il float. Nell'Esempio I di cui sopra, il nostro elemento padre, #container, è “collassato” come se l'elemento img a cui è stato applicato il float non si trovasse nemmeno lì. Questo non è un bug del browser, al contrario è un comportamento atteso ed appropriato. Dal momento che l'elemento con il float era stato originariamente calcolato nel flusso normale e poi rimosso, l'elemento #container non lo considera all'interno dei suoi confini e pertanto si comporta come se non ci fosse nemmeno. Nota: Eric Meyer ha scritto un bellissimo articolo su questo argomento, intitolato Containing Floats, nel quale va molto più a fondo della questione. E' una risorsa molto utile. La buona notizia è che possiamo porre rimedio a questa situazione in svariati modi: se vi state chiedendo se ha a che fare con la proprietà clear allora siete sulla buona strada.

Uno dei modi più comuni per sistemare un elemento padre collassato è di piazzare un elemento con la proprietà clear dopo l'elemento a cui abbiamo applicato il float. Questo obbligherà il padre ad iniziare a rifluire dopo l'elemento con il float. Forse è più semplice mostrarvi ciò in azione. Considerate lo HTML dell'Esempio J che è lo stesso dell'esempio precedente ma con un elemento in più:

 
 
<div id="container">
  <p>This is some text contained within a 
small-ish box. I'm using it as an example
of how placing your floated elements in different
orders in your HTML can affect your layouts. For 
example, take a look at this great photo 
placeholder that should be sitting on the right.</p>
  <img src="/image.gif" />
  <div style="clear: right;"></div>
</div>
 
 

Piazzando un div con uno stile inline clear: right abbiamo fatto in modo che il nostro #container liberi la nostra immagine con il float facendogli ricalcolare la sua altezza ora che c'è un elemento sotto ad essa. Sebbene questa soluzione funzioni, potrebbe non essere la più elegante perché dobbiamo aggiungere del markup extra al nostro documento. Sarebbe stato più intrigante gestire ciò tramite CSS. Ci sono alcuni modi per farlo, pertanto esaminiamone uno di questi.

Prendete questo esempio: un elemento padre che contiene tre immagini a cui è applicato un float. IL nostro HTML è come segue:

 
 
<div id="container">
  <img src="/image.gif" />
  <img src="/image.gif" />
  <img src="/image.gif" />
</div>
 
 

Ed il nostro CSS è così:

 
 
#container {
  width: 260px;
  margin: 0 auto;
  padding: 10px 0 10px 10px;
  background: #aaa;
  border: 1px solid #999;
}
 
img {
  float: left;
  margin: 0 5px 0 0;
}
 
 

Quando guarderete questo esempio in azione, realizzerete rapidamente che il nostro elemento padre non contiene le immagini con il float. Di nuovo, questo è un comportamento atteso perché gli elementi con il float vengono rimossi dal flusso. Pertanto, in accordo con il nostro elemento padre, #container, è vuoto. Osservate ciò nell'Esempio K.

Adesso proviamo a rimediarvi con i CSS invece che aggiungendo del markup HTML al nostro documento, come avevamo fatto precedentemente. C'è un metodo che permette ad un elemento padre di liberarsi di qualunque elemento con il float al suo interno. Usa una proprietà CSS chiamata overflow con il valore hidden. Si noti che la proprietà overflow non era stata creata per questo utilizzo e potrebbe dare dei problemi quali nascondere del contenuto o far apparire delle barre di scorrimento non desiderate. Potete approfondire l'argomento leggendo questo articolo e quest'altro. Tuttavia, ai fini del nostro esempio, applicheremo la proprietà overflow: hidden al nostro elemento padre #container:

 
 
#container {
  overflow: hidden;
  width: 260px;
  margin: 0 auto;
  padding: 10px 0 10px 10px;
  background: #aaa;
  border: 1px solid #999;
}
 
 

Il nostro risultato si trova nell'Esempio L. Piuttosto forte, vero? Un altro metodo che dà risultati simili ma con minori caveat usa lo pseudo-selettore :after. Utilizzando il nostro esempio, il codice sarà:

 
 
#container:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
 
 

In questo caso, il CSS sta piazzando un nuovo elemento dopo il nostro elemento #container, con del contenuto al suo interno (in questo caso, un punto) a cui imposta la visibilità a hidden e senza altezza. Potete trovare una panoramica completa e dettagliata di questa tecnica su Position is Everything.

Infine, Eric Meyer spiega un terzo modo per gestire questo problema nel suo articolo citato sopra, Containing Floats. Secondo la Specifica 2.1 di CSS:

un elemento a cui è applicato float si espanderà fino a contenere gli elementi che discendono da esso.

Quindi, in questo caso, applicare il float al nostro elemento contenitore causerà l'espansione di questo fino a contenere la nostra immagine ed il nostro paragrafo in maniera equivalente ai metodi descritti sopra.

Fondamentalmente, tutte queste soluzioni fanno la stessa cosa: stanno facendo in modo che gli elementi padre rispettino il flusso dei loro figli con il float. Ciascuno ha i suoi meriti e la sua utilità. Dovrete impararli tutti e poi applicare quello che funziona meglio nel vostro caso specifico.

Cose che possono causare una rapida perdita di capelli

Credeteci o meno, ma ci sono alcuni bug dei browser che gli elementi con il float possono sollevare, come il double margin bug ed il 3px Text-Jog. Entrambe esulano dallo scopo di questo articolo, ma state tranquilli che per tutti e due ci sono dei semplici rimedi, se volete supportare i vecchi browser.

Conclusioni

Utilizzando la proprietà float potete riempire la vostra cassetta degli attrezzi per i layout in modi piuttosto forti e “responsive”. Comprendere come funziona ed i principi che la regolano vi darà una base solida per l'utilizzo efficace del float.

Illustrazioni: Carlo Brigatti

Share/Save/Bookmark
 

Discutiamone

Ti sembra interessante? Scrivi tu il primo commento


Cenni sull'autore

Noah Stokes

Noah StokesNoah Stokes è un web designer, developer e socio/co-fondatore di Bold, uno studio web. E' sposato e ha due figli, suona la chitarra ed ama la musica. Potete seguirlo su Twitter (@motherfuton) o sul suo blog Es Bueno.

Questo sito per poter funzionare utilizza i cookie. Per saperne di più visita la pagina relativa all' INFORMATIVA