Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Clearfix: esempi, come si usa, tutorial

Capire il clearfix, stratagemma per la gestione correttamente della proprietà CSS float, e delle sue conseguenze sulla definizione di un layout in CSS.
Capire il clearfix, stratagemma per la gestione correttamente della proprietà CSS float, e delle sue conseguenze sulla definizione di un layout in CSS.
Link copiato negli appunti

Il termine "clearfix" è diventato molto comune dall'avvento dei CSS3 e dall'incremento di popolarità dei framework CSS, come Bootstrap, w3.css, Foundation e cosi via, proprio per questo motivo qualsiasi sviluppatore Front-End ha già dovuto fare i conti con questo misterioso soggetto.

Il clearfix è in realtà un concetto molto semplice, che nasce dalla logica conseguenza della natura degli elementi floattanti (a cui è impostato un valore per la proprietà CSS "float" diverso da "none") mescolati alle capacità del CSS3.

Per capire a fondo in cosa consiste il clearfix, dobbiamo quindi avere una buona dimestichezza con la fluttuazione degli elementi. In questo tutorial vedremo come è possibile andare a "pulire" o terminare la fluttuazione in una modalità compatta ed elegante, grazie al clearfix.

Floating ed elementi flottanti

Facciamo un breve ripasso della natura degli elementi HTML: nelle strutture HTML abbiamo a disposizione due grandi macro-categorie di elementi (non sono le uniche!):

  • gli elementi INLINE: possono essere incanalati orizzontalmente uno dopo l'altro, senza generare interruzioni di riga, ma non sono dimensionabili
  • gli elementi DI BLOCCO: non possono essere incanalati sulla stessa linea, perchè generano un'interruzione e di default coprono tutta la larghezza che hanno a dispozione, e sono dimensionabili

Queste sono le caratteristiche di default degli elementi inline e di blocco. Ne consegue che se vogliamo sistemare e posizionare più elementi di blocco (ad esempio elementi "div") sulla stessa linea, non sarà possibile compiere questa operazione senza variabili aggiuntive:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px;}
</style>
</head>
<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</body>
</html>

In questo caso gli elementi "div" avente classe "box" verranno stilizzati con le regole imposte dal selettore ".box", ma di default compariranno in linea verticale, proprio perchè gli elementi di blocco non vengono incanalati sulla stessa riga.

Possiamo ovviare a questo problema semplicemente impostando la proprietà CSS "float" al valore "left" all'interno del selettore "div.box":

float: left;

In questo modo i nostri "div" verranno rimossi dal normale flusso di interpretazione ed incanalti sulla stessa linea, una dopo l'altro.

Tuttavia ora abbiamo il problema diametralmente opposto: qualsiasi elemento che andremo ad aggiungere dopo l'ultimo div "box" verrà posizionato senza tenere conto del flusso del floating, generando un'incongruenza nel layout. Vediamo un esempio:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: left;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
</style>
</head>
<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

Questo stesso codice può incanalare gli elementi anche sulla destra, se usassimo il valore "right" al posto del valore "left" mantenendo inalterata la struttura HTML:

float: right;

Nel caso di "float. left;" gli elementi vengono prodotti seguendo il normale flusso da sinistra verso destra. Nel caso di "float. right;" invece, gli elementi vengono prodotti seguendo il flusso da destra verso sinistra, dove il primo elemento "div" sarà il primo a partire da destra, e l'ultimo elemento "div" sarà l'ultimo a partire da destra. Possiamo accorgerci di tale comportamento se andiamo a definire dei numeri crescenti come contenuto dei nostri elementi floattanti:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: right;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
</style>
</head>
<body>
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

Interrompere il float in maniera esplicita

Abbiamo dunque ora la necessità di andare ad interrompere il flusso generato dalla proprietà "float", per ripristinare il normale corso di produzione e posizionamento degli elementi.

Per fare questo dobbiamo utilizzare la proprietà CSS chiamata "clear", che si occuperà escluviamente di tale compito. La proprietà "clear" può assumere i seguenti valori:

  • "left": interrompe unicamente il flusso di elementi floattanti impostati tramite "float": "left"
  • "right": interrompe unicamente il flusso di elementi floattanti impostati tramite "float": "right"
  • "both": interrompe sia il flusso di elementi flottanti impostati tramite "float": "left" sia il flusso di elementi flottanti impostati tramite "float": "right"

Nel nostro caso dunque, se prendiamo in considerazione il primo esempio con i "div" che fluttuano da sinistra verso destra, possiamo sia impostare la proprietà "clear" al valore "left" sia al valore "both", tenendo presente che nel secondo caso se avremo elementi floattanti impostati con "float: right" sullo stesso flusso, questo verrà interrotto.

Abbiamo bisogno di un elemento avente display di interruzione che vada quindi ad interrompere il float. Nel nostro esempio andiamo ad impostare un elemento "div" avente classe "clear" (il nome della classe lo definiamo noi) dopo l'ultimo "div" floattante, per interrompere il flusso e far comparire i "div" con classe "box2" DOPO l'ultimo "div". La classe "clear" andrà ad impostare la proprietà CSS "clear" al valore "left":

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: left;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
  div.clear {clear: left;}
</style>
</head>
<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="clear"></div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

In questo modo abbiamo generato un'interruzione dopo l'ultimo "div" con classe "box" che ripristina il flusso standard di interpretazione. Dato che stiamo utilizzando una classe, possiamo produrre N interruzioni posizionate dove vogliamo. Ad esempio, possiamo produrre un effetto "a scalare" andando ad interrompere il float ogni N "div" per produrre 4 righe di elementi, prima dopo 4 "div", per costruire la prima riga, successivamente dopo 3, 2 ed 1 solo "div":

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: left;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
  div.clear {clear: left;}
</style>
</head>
<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="clear"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="clear"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="clear"></div>
  <div class="box"></div>
  <div class="clear"></div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

Dato che abbiamo utilizzato un elemento HTML "distruttore" del flusso di floating, possiamo dire che abbiamo utilizzato un clear "esplicito", senza nessun tipo di hack CSS.

Interrompere il float in maniera implicita

Per andare a produrre un'interruzione di float senza avere l'occorrenza di utilizzare un elemento HTML che si occupi di tale compito, possiamo sfruttare una potente capacità del CSS 3: lo pseudo-elemento.

Gli pseudo-elementi non sono infatti elementi HTML espliciti, scritti a mano nel codice HTML, ma sono elementi generati diretttamente dal CSS e posizionati in una deteriminata zona. Gli pseudo-elementi si dichiarano attraverso il selettore "::" (doppio due punti):

  • ::before genera un elemento PRIMA del contenuto di un elemento HTML
  • ::after genera un elemento DOPO il contenuto di un elemento HTML

Quindi dobbiamo fare attenzione: ::before ed ::after non generano elementi prima e dopo l'elemento stesso, ma prima e dopo il suo contenuto, che è l'area dell'elemento dimensionata dalle proprietà CSS "width" (larghezza) ed "height" (altezza).

Se andiamo quindi a produrre uno pseudo-elemento dopo il contenuto di un elemento HTML, che abbia come proprietà CSS quelle che aveva il nostro "div" con classe "clear" costruito in precedenza, questo elemento andrà a terminare il float dei suoi elementi in maniera implicita. L'elemento a cui andiamo ad impostare questa capacità sarà dunque un elemento contenitore:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: left;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
  div.row::after {
    clear: both;
    display: block;
    content: "";
  }
</style>
</head>
<body>
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

In questo caso abbiamo incluso tutti i nostri elementi "div" floattanti (con classe "box") all'interno di un "div" con classe "row", che ha impostato uno pseudo-elemento nel seguente modo:

div.row::after {
    clear: both;
    display: block;
    content: "";
}

Questa linea di codice indica che dopo il contenuto di ogni elemento "div" con classe "row" deve essere generato un elemento avente proprietà CSS "clear" con valore "both", proprietà "display"con valore "block" e proprietà "content" con valore "" (il valore del contenuto dello pseudo-elemento).

Dato che il contenuto dei "div.row" termina con un elemento "div.box", significa che dopo questo elemento verrà applicato un clear. Questo "pseudo-clear" possiamo definirlo finalmente come "clearfix", ovvero la sistemazione del float implicita.

Questa capacità è molto più elegante rispetto alla precedente. Per produrre ad esempio le righe composte da elementi "div" floattanti a numero descresente, possiamo ora scrivere quanto segue:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>float-clear</title>
<style>
  div.box {width: 100px; height: 100px; background-color: blue; margin: 10px; float: left;}
  div.box2 {width: 100px; height: 100px; background-color: red; margin: 10px;}
  div.row::after {
    clear: both;
    display: block;
    content: "";
  }
</style>
</head>
<body>
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="row">
  <div class="box"></div>
</div>
  <div class="box2"></div>
  <div class="box2"></div>
</body>
</html>

Come possiamo vedere utilizzando questo codice, ogni "div" con classe "row" andrà a contenere N elementi "div" floattanti ed andrà a produrre un clear all'apposita locazione, ripristinando il flusso dove occorre. Il risultato è identico alla soluzione di "clear" esplicito, ma senza utilizzare N "div.clear" posizionati esplicitamente dove è necessario. Possiamo dire che nel secondo caso questo compito viene sgravato dallo sviluppatore.

Conclusione

Il clearfix è una potente tecnica HTML-CSS utilizzatissima nei layout moderni, sia composti nativamente sia composti tramite framework CSS professionali, come quelli citati ad inizio articolo.

La suddivisione (o il sezionamento) di un layout HTML in righe e colonne è possibile in maniera modulare ed elegante grazie al clearfix.

Vediamola in azione in un contesto più avanzato. Se ad esempio vogliamo creare un layout nativo (senza l'utilizzo di framework CSS) moderno, composto da 3 righe, ognuna composta rispettivamente da:

  • 3 elementi di eguale dimensione
  • 3 elementi di dimensioni 20-60-20
  • 1 elemento a tutta pagina

scriveremo quanto segue:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>flot-clear</title>
<style media="screen">
  .row {width: 100%;}
  .row::after {clear: both; content: ""; display: block;}
  .row > div {height: inherit; float: left;}
  .w33 {width:33.33%;}
  .w20 {width:20%;}
  .w60 {width:60%;}
  .w100 {width:100%;}
  .h80 {height: 80px;}
  .h400 {height: 400px;}
  #top-left {background-color: red;}
  #top-center {background-color: green;}
  #top-right {background-color: blue;}
  #center-left {background-color: pink;}
  #center-center {background-color: orange;}
  #center-right {background-color: violet;}
  #bottom {background-color: yellow;}
</style>
</head>
<body>
<div id="container">
  <div class="row h80">
    <div id="top-left" class="w33"></div>
    <div id="top-center" class="w33"></div>
    <div id="top-right" class="w33"></div>
  </div>
  <div class="row h400">
    <div id="center-left" class="w20"></div>
    <div id="center-center" class="w60"></div>
    <div id="center-right" class="w20"></div>
  </div>
  <div class="row h80">
    <div id="bottom" class="w100"></div>
  </div>
</div>
</body>
</html>

Con le classi "w*" andiamo a produrre elementi di larghezza percentuale variabile. Con le classi "h*" andiamo a produrre un altezza esplicita e fissa alle righe (elementi contenitori di elementi floattanti) che verrà ereditata da tutti gli elementi contenuti (e figli diretti) nelle righe stesse. Con i singoli "id" andiamo infine a definire gli stili di ogni sezione. Abbiamo poi il nostro "clearfix" applicato a tutte le righe che si occuperà di produrre.

In poche righe di codice HTML e CSS abbiamo dunque prodotto un layout fluido, flessibile e modulare. La potenza delle nuove specifiche è davvero elevata.

Ti consigliamo anche