La principale proprietà per posizionare un elemento in una posizione fissa è sticky, questa è studiata per fissare elementi in una determinata posizione che rimarrà fissa anche in caso di scroll dall’utente e ridimensionamento.
Il principale uso di questa tecnica è la creazione di barre fisse in alto ad una pagina o in posizione finale come footer. La documentazione ufficiale è ricca di esempi che si possono riassumere con una sola classe:
div.sticky { position: -webkit-sticky; /* Safari */ position: sticky; top: 0; }
Un elemento con questo tipo di classe è una alternativa al posizionamento relative e fixed ma dipende solo dalla posizione della scrollbar, esso si posiziona relativamente al contenitore e viene fissato allo schermo, purtroppo Internet Explorer, Edge 15 e vecchie versioni dei browser non supportano questa proprietà mentre il browser Safari richiede l’aggiunta di una proprietù specifca con il prefisso webkit.
Fin dalla prima versione di CSS, la proprietà float è stata una delle più usate per la creazione di layout e parti di pagine, nonostante gli tanti sforzi non esiste un vero standard in quanto con l’uso di questa proprietà visto che è possibile posizionare elementi nella pagina non in maniera “sequenziale” come vorrebbe lo standard HTML, d’ora in avanti in questo articolo parleremo di elementi fluttuanti come qualsiasi tag con la proprietà float impostata con qualsiasi valore, per ogni dubbio rimando sempre alla guida W3C.
La prima caratteristica degli elementi fluttuanti è che sono impostati come block-level, in poche parole questo significa che sono elementi blocco indipendente da quello che gli sta attorno e che hanno una propria altezza e una propria altezza che viene calcolata automaticamente dal contenuto, la caratteristica principale è che il contenitore dell’elemento non si adatta a questa altezza automaticamente, infatti si possono creare situazioni del tipo:
cioè l’elemento verde (il contenitore) non si auto-adatta alle dimensioni dell’elemento in giallo (che è quello fluttuante contenuto), l’elemento blu (che è il successivo) si posizione dove trova posto infatti si posiziona a sinistra dell’elemento fluttuante, questo perché (come dice la parola stessa) il fluttuare crea spazi che i browser provano a riempire, per evitare questo si deve usare la proprietà clear che vedremo in seguito. Uno dei problemi più grandi degli elemento fluttuanti è che si auto-adattano in larghezza quindi può capitare di perderne il controllo, conviene sempre impostare la larghezza dell’elemento fluttuante oppure, ancora meglio, impostare la larghezza del contenuto dell’elemento, poi il fluttuante si adatta alla larghezza.
Il problema più grave che affligge grafici e programmatori web è che gli elementi fluttuanti, tendono ad uscire dal contenitore e che gli elementi successivi possono posizionarsi in posizioni non volute, per risolvere questo problema negli anni sono state create molti ipotesi e filosofie, la più comune prima dello standard CSS3 era creare dei tag div che fungessero da “interruzione di float” detta anche Clearfix, tecnica descritta nella documentazione ufficiale come un elemento invisibile che divide gli elementi evitando sovrapposizione indesiderate. Per fare questo bastava creare una classe:
<div style=”clear:right”> </div>
con questo stile si indica che questo div non deve avere elementi fluttuanti a destra e a sinistra, quindi qualsiasi elemento successivo viene disegnato come se nulla ci fosse sopra. Questo ha però un grande difetto: inserire nelle pagine HTML un tag vuoto in tutti i punti, quindi il controllo degli elementi fluttuanti non è fatto via CSS ma via HTML, cosa chiaramente non positiva per i grafici. Da notare che questo div (essendo vuoto e fluttuante) non è visibile e non crea danni alla struttura grafica della pagina. Negli anni poi ci sono molti tentativi di sistemare la cosa in maniera più elegante ma con CSS3 il problema è stato risolto definitivamente con una tecnica evoluta: l’uso della proprietà after: in c’è un tag con un figlio fluttuante basta aggiungere la caratteristica
.clearfix::after { content: ""; clear: both; display: table; }
per indicare che qualsiasi tag successivo al contenitore deve ignorare l’elemento fluttuante e si posiziona dopo come se “nulla fosse”, da notare che abbiamo dovuto inserire uno spazio dopo per creare un elemento vuoto e mostrare la disposizione tabellare. Il nostro esempio quindi diventa:
Una tecnica mista di posizionamento combinata con il posizionato fluttuante è fissare un elemento in base a valori fissi, per esempio questa tecnica può essere usata per fissare un elemento a fine pagina come footer, la documentazione ufficiale presenta un bellissimo esempio:
<style> .footer { position: fixed; left: 0; bottom: 0; width: 100%; background-color: red; color: white; text-align: center; } </style> ... <div class="footer"> <p>Footer</p> </div>
La gestione di CSS è limitata all’uso di classi assegnati a uno o più elementi di una pagina, le pseudo-classi permettono di modificare il comportamento a seconda dello stato di un elemento, la sintassi prevede l’uso di creare una classe dove oltre al nome si indica, con due-punti, il nome della pseudo-classe. Uno dei semplici utilizzi di questa tecnica è il cambiare colore di un link quando il mouse passa sopra, questo comportamento può essere regolato con l’uso della pseuso classe “hover”
a { color: blue; } a:hover { color: #FF00FF; }
L’elenco completo di tutte le classi è disponibile al sito di mozilla ma bisogna ricordare che non tutte le classi sono disponibili in tutti i browser.
I più comuni e più usati sono:
:empty
usato per modificare l’aspetto di elementi vuoti:focus :disabled :enabled :checked :invalid :read-only
usati per determinare lo stato di un input e modificarne l’aspetto e il comportamento:first-child :last-child :last-of-type
usato per modificare l’aspetto del primo o dell’ultimo figlio di un elemento:is() :not()
usato per modificare l’aspetto di elementi con caratteristiche specifiche condizionali:nth-child() :nth-last-child() :nth-last-col() :nth-last-of-type() :nth-of-type()
usato per modificare l’aspetto degli elementi di un gruppo:only-child
usato per modificare l’aspetto di un oggetto se unico figlio del suo contenitore:root
usato per modificare l’aspetto dell’oggetto principale, spesso usato per identificare il tag HTML radice di un documento
La documentazione ufficiale è disponibile, come sempre, nel sito della w3schools. In particolare il gruppo dei nth è usato per gestire i gruppo di figli come righe di una tabella, elementi di una lista o semplici elementi dentro ad un altro elemento, un uso semplice è andare posizionali, per esempio volendo colorare il quarto elemento:
tr:nth-child(4) td {background-color: red}
questa tecnica è usata per distinguere poi elementi alla posizione pari da quelli alla posizione dispari con:
tr:nth-child(even) tr:nth-child(2n) tr:nth-child(odd) tr:nth-child(2n+1)
Ed è possibile selezionare un elemento partendo dal fondo , per esempio per colorare di giallo il penultimo elemento di un gruppo
tr:nth-last-child(2) td { background-color: yellow}
La pseudo-classe target consente di selezionare un elemento della pagina che corrisponde ad un indirizzo: data una pagina con delle ancore al proprio interno, la pseudo-classe E:target ci consente di assegnare uno stile all’elemento di destinazione nel momento in cui è selezionato. Un esempio per comprenderne il funzionamento partendo dal codice dove al click di un link viene evidenziato in rosso il blocco sottostante:
<style> div:target {color:Red;} </style> <ul> <li><a href="#div1">Div1</a></li> <li><a href="#div2">Div2</a></li> <li><a href="#div3">Div3</a></li> <li><a href="#div4">Div4</a></li> </ul> <div id="div1"><p>Testo1 ....</p></div> <div id="div2"><p>Testo2 ...</p></div> <div id="div3"><p>Testo3...</p></div> <div id="div4"><p>Testo4 .... </p></div>
Con le pseudo-classi logiche è possibile creare delle mini-condizioni con gli operatori is e not, per esempio è possibile usare not in combinazione con altri pseudo-classi, per esempio:
input:not(:disabled){color: black;}
per modificare l’aspetto di elemento che non hanno determinate caratteristiche. Ma è possibile usare la stessa tecnica per creare logiche sulle classi, cioè selezionare elementi che non hanno determinate classi:
div{color:white;} div:not(.white) {color: black}
Gli pseudo-elementi son un’altra tecnica che prevede l’uso di parole chiave per modificare l’aspetto di parti di un elemento, rispetto alle pseudo classi che modificano tutto l’elemento, da CSS3 gli pseudo-elemento si differenziano dalle pseudo-classi perché si usano due caratteri di due punti ::
invece che uno solo, per mantenere la retro-compatibilità con il codice esistente, i browser sono tenuti a supportare entrambe le sintassi, la più comuni sono:
::before ::after ::first-letter ::first-line
Gli pseudo-elementi sono supportati, salvo qualche dettaglio di ::before e ::after, da tutti i principali browser. Le prime due permettono di creare elementi prima o dopo un elemento, per esempio:
#element:before { content: ""; display: block; width: 100px; height: 100px; } ... <div id="element">ciao</div>
Questo semplice esempio, prima del div, aggiunge un elemento vuoto ma di larghezza e altezza come indicato nella classe, bisogna però sempre ricordarsi di mettere la proprietà content anche se vuota in quanto omettendola alcuni browser non creano nessun elemento. Inoltre bisogna sempre ricordare che l’elemento inserito con questa tecnica è un elemento in-line per dare un volume all’elemento ma talvolta è necessario definirlo esplicitamente come un elemento a livello di blocco (con display:block). L’uso di before e after è anche condizionato dal fatto che, il contenuto che viene inserito attraverso i CSS, sarà un contenuto figlio in relazione all’elemento e ma verrà posizionato prima oppure dopo di qualsiasi altro contenuto in quell’elemento e mentre si sviluppa con questi pseudo-elementi bisogna considerare che non sono “reali” perché non fanno parte del documento DOM, quindi non bisogna mai utilizzare gli pseudo-elementi per generare contenuti dinamicamente o che siano fondamentali per l’usabilità o l’accessibilità delle pagine perché rischiano di sparire e non tutti i browser si comportano bene con questi elementi. Personalmente gli evito se posso.
In fase di studio del layout di un sito bisogna considerare la struttura a blocchi dei siti responsive: non è possibile incastrare le componenti senza allineamenti e bisogna evitare di creare strutture a tetris, come in immagine, che potrebbero anche essere impossibili con tecnologie HTML e non possono essere facilmente adattate ai dispositivi mobili.
Durante lo studio e la progettazione di un sito responsive bisogna sempre tenere conto che gli oggetti dovranno essere visualizzati anche sui dispositivi mobili come gli smartphone e monitor molto grandi come i monitor molto grandi quindi nel disegno di un sito non si può pensare di inserire un oggetto statico ma bisogna sempre pensare alla sua rappresentazione grafica sui diversi dispositivi, allo stesso tempo bisogna cercare di non limitare troppo il “canale” internet, trovare un compromesso è possibile usando il box-modeling e lo studio degli elementi flessibili, in questo articolo sarà introdotto il primo concetto mentre il secondo sarà introdotto in futuri articoli.
Il concetto di box-modeling è uno dei punti più importanti dei fogli di stile CSS e ogni designer deve conoscere molto bene questi concetti: fin dalla prima versione dell’HTML e dei CSS ogni programmatore è sempre afflitto da dove e come posizionare gli oggetti HTML rispetto agli altri, infatti per box-modeling si intende definire le posizioni e le distanze tra i vari oggetti usando le varie proprietà di altezza, larghezza, margine, bordi e padding. Fin dalla versione 2 di CSS si è definito uno standard sui box e non è variata molto nella versione 3: ogni elemento ha un margine, un bordo, un padding, larghezza e altezza che vengono definite con proprietà specifiche:
le proprietà di larghezza e altezza (width e height) imposta le dimensioni di elementi esclusi padding, margini e bordi che vengono sommati a posteriori. Per rendere CSS più flessibile possibile è possibile modificare l’impostazione della somma delle larghezze usando la proprietà box-sizing che può assumere due valori:
- content-box: il valore di larghezza fa riferimento all’area del contenuto (valore di default)
- border-box: il valore di larghezza fa riferimento al box nella sua interezza, comprendendo anche il padding e il bordo.
Quindi, per esempio:
#divProva{ width:100px; padding:2px; border: 1px solid black; box-sizing:border-box; }
la larghezza di 100 pixel comprende anche bordi e padding.
Una delle proprietà più interessanti fin alla prima versione di CSS è la proprietà inline che gestisce la grande differenza che di default si trova tra i tag DIV e SPAN, SPAN infatti ha come valore display mentre per il tag DIV (e molti altri) il valore di default è block. Semplificando i comportamenti della proprietà: un elemento SPAN (o qualsiasi elemento con inline:display
) si prenda meno spazio possibile mentre un elemento DIV (o qualsiasi elemento con inline:block
) si prende tutto lo spazio disponibile sulla riga a meno che non sia indicata una larghezza con la proprietà width.
Un semplice esempio del diverso comportamento tra queste proprietà e tra i tag DIV vs SPAN:
<span style="background-color:red;">primo span</span> <span style="background-color:blue;color:white;">secondo span</span>
primo spansecondo span
mentre usando il tag DIV (o il tag P) il risultato è:
<div style="background-color:red;">primo div</div> <div style="background-color:blue;color:white;">secondo div</div>
primo div
secondo div
Il valore inline ha un grande difetto: non interpreta le proprietà larghezza (width) e altezza (height) ma le assegna in base al contenuto dell’oggetto: se abbiamo un link il cui contenuto occupa 100px in larghezza, anche impostando una larghezza maggiore, lo spazio occupato dall’elemento con inline sarà sempre di 100 pixel, questo problema può risultare scomodo negli elementi grafici dove le aree visibili o cliccabili sono maggiori di quella effettivamente occupata dal testo ma può invece essere sfruttata per evitare che certi tag aumentino le dimensioni senza controllo.
Gli elementi di tipo blocco hanno sempre la proprietà display con valore block. Sono, ad esempio, i paragrafi e tutti i tag di heading (h1, h2, h3, …), questi elementi assumono le dimensioni impostate nel CSS se specificate e, salvo utilizzo della proprietà float, non accettano altri oggetti sulla stessa riga prendendo tutto lo spazio a disposizione. Proprio per questo motivo il tag SPAN è poco usato e la proprietà inline è usata molto di rado, infatti per affiancare più elementi (come blocchi) vengono usati gli elementi fluttuanti che possono gestire le larghezze in maniera nativa.
Con le proprietà flexbox sono state introdotte alcune nuove caratteristiche per creare strutture di layout non lineari come previsto normalmente da CSS, senza i quali al programmatore rimane solo l’uso della proprietà float. Questa è stata pensata per rendere semplice la gestione di elementi interni ad un elemento contenitore e per risolvere le varie problematiche legate alla centratura degli elementi rispetto agli assi verticali e orizzontali. Per usare queste proprietà bisogna tenere conto di due aspetti costruttivi:
- un elemento contenitore che contiene gli elementi flessibili indicato con la proprietà
display:flex
- gli elementi flessibili dove non bisogna dedicare nessuna proprietà specifica.
All’elemento padre si deve poi aggiungere la proprietà addizionale per indicare l’allineamento verticale con la proprietà align-items: center;
Agli elementi figli è possibile poi aggiungere delle caratteristiche ulteriore:
- modificare l’allineamento dello specifico elemento con la proprietà
align-self
- modificare l’ordine di visualizzazione con la proprietà order
Un esempio pratico è:
<div style="display:flex;align-items: center;"> <div style="background-color:red;">rosso</div> <div style="background-color:yellow;">giallo<br /> a capo</div> <div style="background-color:green;text-align:center;">verde</div> <div style="background-color:gold;order:-2;">oro con ordine</div> <div style="background-color:lightblue;align-self:flex-start;">azzurro</div> <div>
E il risultato di questo semplice esempio è:
a capo
Usando il Response Designe con il sistema a Box scegliendo la tecnica delle media-queries, per crare una pagina di esempio blocchi con il classico schema:
- versione internet: più righe con il primo box largo tutta la pagina, nelle successive righe i blocchi sono affiancati dove possibile
- versione tablet: i blocchi rimangono affiancati
- versione mobile: i blocchi sono uno sotto l’altro senza nessun affiancamento
Un esempio di codice che implementa questa logica:
<!DOCTYPE html> <html> <head> <style> DIV { box-sizing: border-box;} body{ margin:0; padding:0; background-color:lightgreen; } .gliglia{margin: 0px auto; background-color:lightblue; padding: 25px;} .grid{float: left; padding-left: 25px;position: relative; width: 100%;width: 100%;} .elemento{height:100px; background-color:gold;} .riga{margin-left: -25px;} @media only screen and (min-width: 480px) and (max-width: 599px) { .elem1{width: 100%;} .elem2{width: 100%;} .elem4{width: 100%;} } @media only screen and (min-width: 600px) and (max-width: 1024px) { .elem1{width: 100%;} .elem2{width: 100%;} .elem4{width: 50%;} } @media only screen and (min-width: 1025px) { .gliglia{width: 1040px;} .elem1{width: 100%;} .elem2{width: 50%;} .elem4{width: 25%;} } .riga:before, .riga:after{content: " "; display: table;} .riga:after, .gliglia:after{ clear: both;} </style> </head> <body> <div class="gliglia"> <div class="riga"> <div class="grid elem1"> <p class="elemento">1 int, 1 tablet, 1 mobile</p> </div> </div> <div class="riga"> <div class="grid elem2"> <p class="elemento">1/2 int, 1 tablet, 1 mobile</p> </div> <div class="grid elem2"> <p class="elemento">1/2 int, 1 tablet, 1 mobile</p> </div> </div> <div class="riga"> <div class="grid elem4"> <p class="elemento">1/4 int, 1/2 tablet, 1 mobile</p> </div> <div class="grid elem4"> <p class="elemento">1/4 int, 1/2 tablet, 1 mobile</p> </div> <div class="grid elem4"> <p class="elemento">1/4 int, 1/2 tablet, 1 mobile</p> </div> <div class="grid elem4"> <p class="elemento">1/4 int, 1/2 tablet, 1 mobile</p> </div> </div> </div> <div class="riga"> <div class="grid elem1">footer</div></div> </body> </html>
In questo esempio non è stato usato il tag <TABLE>, impossibile da usare con le media-queries, quindi sono usati dei tag <DIV> ai quali è stata impostata la una caratteristiche molto importante:
DIV { box-sizing: border-box;}
per poi poter usare le percentuali sulle larghezze: storicamente un elemento HTML (non solo i tag DIV) hanno una larghezza ma di default la larghezza non comprende i margini che vengono calcolati a parte, con questa proprietà la larghezza e l’altezza dei bordi viene compresa nella definizione nei CSS e si evitano sorprese: per esempio con due elementi al 50% e un po’ di bordo, senza questa proprietà il secondo elementi andrebbe a capo in quanto il bordo del primo elemento porterebbe la larghezza ad almeno il 51% e non ci sarebbe abbastanza spazio, per maggiori dettagli si rimanda alla pagina W3C.
Successivamente sono stati impostati margini del BODY per eviatre di perdere spazio:
BODY{ margin:0; padding:0; background-color:lightgreen; }
La classe griglia vuole essere solo un contenitore di righe, in poche parole sarebbe il <table> della nostra struttura, non sarebbe necessario ma è sempre buona norma mettere un div contenitore per poter aggiungere impostazioni che, altrimenti, sarebbero complicate da mettere nei vari elementi della struttura, in questo esempio abbiamo definito un colore e un padding, la larghezza non è indispensabile perché se non specificata il tag DIV si “prende” tutto lo spazio che trova. La classe riga è la definizione delle caratteristiche “orrizzontali” del gruppo di elementi, si può pensare come un <TR> ma con una caratteristica diversa: questo non contiene un numero fisso di elementi. La classe grid è la più interessante dell’esempio perchè definisce che ogni elemento della griglia è fluttuante e indica che la posizione deve essere relativa (di solito è il default ma meglio ridefinirlo per evitare brutte sorprese), questo è semplicemente il contenuto di ogni elemento della griglia e in questo esempio abbiamo definito un aspetto grafico: altezza e colore per poter identificare ogni box, da non confondere il contenuto con l’elemento fluttuante: sempre meglio fare due tag per evitare conflitti tra le proprietà e i tag.
Le successive classi sono definite con le media queries e cioè pezzi di css condizionati ad alcune caratteristiche, in questo caso ci sono definiti tre blocchi con dove sono definite le stesse classi ma con valori percentuali diverse, il primo per il mobile (minimo 480 e massimo 599), il secondo per tablet (minimo 600 massimo 1024) e il terzo per i browser internet (con monitor con più di 1024 pixel):
@media only screen and (min-width: 480px) and (max-width: 599px) { ... } @media only screen and (min-width: 600px) and (max-width: 1024px) { ... } @media only screen and (min-width: 1025px) { .gliglia{width: 1040px;} ... }
Le ultime due righe dello stile sono le più complicate da spiegare e un occhio esperto potrebbe essere infastidito, perché sono la definizione di due condizioni sulle righe, indispensabili per evitare i problemi con gli elementi fluttuanti, la prima riga aggiunge prima e dopo un elemento di classe riga uno spazio e indica che i figli di elemento devono essere disposti a tabella, per maggiori dettagli vi consiglio di studiare la pagina W3C:
.riga:before, .riga:after{content: " "; display: table;} .riga:after, .gliglia:after{ clear: both;}
La seconda classe invece è fondamentale, perche impone che alla fine di ogni riga (e alla fine della griglia) non ci siano altri elementi fluttuanti, con il valore both si indica al browser che non ci deve essere altro a sinistra e a destra dell’elemento quindi il browser sarà costretto a posiziona gli elementi successivi sotto, questa proprietà è spesso mal vista ma ormai indispensabile per chi vuole sviluppare uno stile responsivo, consiglio comunque la pagina W3C.