Scegliere come posizionare un elemento nei CSS a volte è davvero una scelta su quali effetti collaterali sono più accettabili.
Posizionare i layout nei CSS era una volta un compito molto scoraggiante, e hack come l’uso di tabelle per l’intero layout erano abbastanza comuni. Nel corso degli anni, la richiesta di migliori strumenti di layout ha portato a un supporto e a tecniche sempre migliori.
Oggi abbiamo delle opzioni, e imparare a gestire ciascuna di queste tecniche è la chiave per creare layout complessi che rimangano facili da cambiare e abbastanza flessibili da gestire diverse dimensioni dello schermo.
- Grid
- Flexbox
- Position
- Floats
Grid
Grid è il modo più recente per creare layout sul web. È un potente insieme di regole che permettono di posizionare gli elementi su un piano verticale e orizzontale.
A differenza di flexbox, grid dovrebbe essere usato per layout di pagina più grandi. Flexbox può, e dovrebbe, essere collocato all’interno di un layout a griglia per aiutare a posizionare i componenti che un layout a griglia contiene. Il supporto dei browser per la griglia è ottimo, salvo alcuni problemi con Internet Explorer che richiedono un prefisso del fornitore per gestire una versione precedente della specifica.
Ci sono un sacco di proprietà e funzioni da imparare per implementare la griglia, ma una volta messa in atto fa miracoli per mantenere i vostri layout flessibili e manutenibili.
Ecco come iniziare con un layout a griglia nella vostra pagina:
<body> <header></header> <nav></nav> <main></main> <footer></footer> </body>
body { display: grid; }
Ecco fatto! Non vedrete ancora alcun cambiamento visivo con questa configurazione perché, a differenza di flexbox, la direzione predefinita del layout è per riga (il che significa che gli elementi sono impilati verticalmente l’uno sull’altro). Ma hai fatto un passo importante nell’impostazione del tuo nuovo layout a griglia – tutti gli elementi figli di primo livello di body
sono ora elementi della griglia! Ora puoi controllare la loro posizione, il loro allineamento e la loro larghezza con poche altre dichiarazioni.
Modelli di colonna e di riga
grid-template-rows
e grid-template-columns
sono proprietà che definiscono esplicitamente il dimensionamento della griglia in orizzontale (colonna) o in verticale (riga). Puoi definire solo una direzione o entrambe! Potete definire la dimensione di ogni elemento della griglia con una varietà di unità di misura. L’ordine dei valori nella griglia sono applicati rispettivamente all’ordine degli elementi nel DOM all’interno del contenitore della griglia (es. nell’esempio qui sotto, se il primo elemento nel corpo è l’intestazione, otterrà un’altezza di riga di 100px)
body { display: grid; grid-template-rows: 100px 5rem auto 30%; }
È possibile creare colonne e righe della griglia implicite con grid-auto-rows
e grid-auto-columns
che richiedono solo un singolo valore di misura che si applicherà a tutti gli elementi figli diretti nella griglia.
body { display: grid; grid-auto-rows: 30px; }
Auto flow
grid-auto-flow
controlla come gli elementi vengono automaticamente posizionati nella griglia. Questa proprietà è molto simile a flex-direction
perché dirige l’impilamento automatico degli elementi, in verticale o in orizzontale. Il valore predefinito è row
, ma un valore di column
può essere utilizzato in modo che gli elementi siano posti uno accanto all’altro lungo l’asse orizzontale. Puoi usare grid-auto-flow
senza impostare le dimensioni per le righe/colonne del template se stai semplicemente cercando di cambiare la direzione di impilamento.
body { display: grid; grid-auto-flow: column; }
Inoltre, è possibile impostare un valore di dense
che mira a “riempire i buchi” il prima possibile nella griglia. Potete anche specificare la direzione della densità con column dense
o row dense
. L’avvertenza all’uso di questo valore è che potrebbe mettere un elemento fuori ordine nella tua griglia nel tentativo di occupare qualsiasi spazio vuoto inutilizzato.
body { display: grid; grid-auto-flow: row dense; }
L’unità frazionaria
Grid introduce anche una nuova unità chiamata frazione o fr
fr
definisce la proporzione che un elemento deve occupare rispetto al suo contenitore (si pensi alla miscelazione di un cocktail: 7 parti di gin e 1 parte di vermouth secco per fare un martini). Nell’esempio qui sotto, i primi due elementi della griglia occuperanno proporzioni uguali, mentre il terzo elemento occuperà tre volte le dimensioni dei primi due; l’ultimo elemento avrà le stesse dimensioni dei primi due.
body { display: grid; grid-template-rows: 1fr 1fr 3fr 1fr; }
Aree template della griglia
grid-template-areas
assegna dei nomi alle celle della griglia che possono essere referenziati negli elementi figli per posizionarli sulla griglia. La cosa bella delle aree della griglia è che stai disegnando la tua griglia con una dichiarazione (questo rende anche le media query incredibilmente semplici). Ogni stringa separata (all’interno di ogni blocco di citazioni) rappresenta una riga distinta; ogni elemento all’interno di quella stringa rappresenta una colonna distinta. Puoi distribuire un elemento su più colonne o righe ripetendo il nome (le celle devono formare una forma rettangolare; non puoi disgiungerle). Questo metodo di nominare le aree della griglia è utile quando si ha a che fare con un layout di pagina di alto livello per la leggibilità in una complessa trapunta di elementi.
body { display: grid; grid-template-areas: "head head" "nav main" "foot foot"; }
Le aree del modello definite sopra devono corrispondere a particolari elementi utilizzando la proprietà grid-area
.
header { grid-area: head; } nav { grid-area: nav; } main { grid-area: main; } footer { grid-area: foot; }
body { display: grid; grid-template-areas: "head ." "nav main" "nav foot"; }
Gli elementi della griglia possono essere organizzati in qualsiasi ordine. Ma fate attenzione ai problemi di accessibilità con il riordino totale degli elementi DOM, poiché può essere un’esperienza frustrante con gli screen reader e il tabbing.
body { display: grid; grid-template-areas: "foot . ." "main nav nav" "head head head"; }
La funzione repeat
Se volete creare un modello di misura per i vostri elementi della griglia (senza scrivere lo stesso valore più e più volte), potete usare la funzione repeat. Questa funzione prende due argomenti: numero di ripetizioni e larghezza/altezza di ogni colonna o riga. Nell’esempio qui sotto, ogni riga della griglia occuperà un’altezza uguale su 3 colonne. Questo definirà anche l’avvolgimento degli elementi nella tua griglia.
body { display: grid; grid-template-columns: repeat(4, 1fr); }
Un modello di ripetizione può anche prendere più valori di misura per definire un modello più complesso.
body { display: grid; grid-template-columns: repeat(2, 100px 1fr); }
È anche importante notare che grid ha introdotto altre utili funzioni come minmax e fit-content.
Grid gap
Forse la proprietà più eccitante ora disponibile è grid-gap
, che imposta i gutters o gap tra righe e colonne. Prima che esistesse questa comoda funzione, impostare gli spazi vuoti era un compito arduo che richiedeva margini negativi e calcoli precisi della larghezza.
grid-gap
è l’abbreviazione di row-gap
e column-gap
e accetta quasi tutti i valori di misura. Scrivendo un singolo valore si applica lo stesso scarto sia alle righe che alle colonne; scrivendo 2 valori separati uno accanto all’altro si applica ogni scarto rispettivamente alle righe e alle colonne. Se vuoi specificare uno spazio solo per le colonne o per le righe, usa row-gap
o column-gap
con un solo valore.
body { display: grid; grid-auto-rows: 30px; grid-gap: 2rem; }
Colonna e riga della griglia
Non tutto il posizionamento della griglia deve essere fatto all’interno dell’elemento padre; gli elementi figli prendono alcune proprietà per un maggiore controllo. grid-area
è usato per definire la posizione di un elemento quando si usa grid-template-area
(dettagliato in una sezione precedente). Se la tua griglia è disegnata con template o righe/colonne automatiche, puoi posizionare con precisione gli elementi su specifiche linee della griglia. Per fare questo puoi usare le proprietà grid-column
e/o grid-row
. Queste sono abbreviazioni per grid--start
e grid--end
, separate da una barra (per esempio grid-column: grid-column-start / grid-column-end
).
È importante notare che le linee della griglia iniziano e finiscono sul contenitore esterno e sono numerate a partire da 1. Per esempio, una griglia con 6 colonne avrà 7 linee di griglia.
body { display: grid; grid-template-columns: repeat(6, 1fr); } header { grid-column: 2 / 4; }
Possiamo anche dire a un elemento della griglia di distribuirsi su un certo numero di colonne o righe con span
.grid { display: grid; grid-template-columns: repeat(6, 1fr); } header { grid-column: span 3; }
Autoallineamento
Nella sezione flexbox, discuteremo l’allineamento dei genitori con align-content
justify-content
align-items
e justify-items
(che si applicano anche alla griglia). Ora, possiamo applicare alcune proprietà simili agli elementi figli stessi con align-self
e justify-self
. Entrambi prendono valori stringa come center
start
e end
Align-self
si allinea sull’asse del blocco, mentre justify-self
si allinea sull’asse in linea. L’allineamento prende la quantità di spazio che il contenuto all’interno dell’elemento della griglia occupa e lo posiziona di conseguenza.
body { display: grid; height: 100vh; } footer { align-self: end; }
Se vuoi semplificare ancora di più, puoi usare la proprietà abbreviata place-self, che imposta rispettivamente align-self
e justify-self
. È possibile utilizzare due valori per posizionare un elemento, o un valore che viene applicato ad entrambe le proprietà. Questo rende la centratura un gioco da ragazzi.
body { display: grid; height: 100vh; } main { place-self: center; }
Il passato e il futuro della griglia
La griglia è forse una delle tecniche di layout più potenti a nostra disposizione in questo momento sul web ed è stata anche una delle più veloci adozioni di una specifica da parte dei principali browser. Se state ancora supportando IE, tuttavia, notate che potete ancora usare grid con un po’ di autoprefixing. Edge, d’altra parte, supporta pienamente la griglia senza bisogno di prefissi.
Guardando al futuro, probabilmente aggiorneremo questo post per includere una caratteristica chiamata subgrid, che ci permetterà di annidare facilmente le griglie!
Flexbox
Un buon modo per gestire elementi di dimensioni variabili è usare le nuove proprietà flexbox introdotte in CSS3.1. Questo ci dà molte più opzioni per controllare il layout e ha risolto alcuni dei problemi di lunga data nei CSS. Il supporto dei browser è buono, e con un polyfill o fallback per portare Internet Explorer a velocità, è pronto per l’uso in produzione.
Ho detto che non avremmo parlato di come funziona il CSS, ma flexbox è ancora nuovo e purtroppo la sintassi è molto confusa. Flexbox è uno strumento così potente e sostituisce così tante altre soluzioni approssimative, quindi vale la pena prendersi del tempo per capire come usarlo.
Partiamo. Ecco come impostare un elemento per usare flexbox.
<div class="container"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div>
.container { display: flex; flex-direction: row; }
Impostare il contenitore su display: flex
permette semplicemente al browser di sapere che intendiamo che i figli usino flexbox per il loro layout. Poi aggiungiamoflex-direction: row
ai figli per allinearli orizzontalmente, e per default avranno la stessa larghezza a meno che non abbiano una larghezza impostata.
Flex-direction
Flex-direction ti permette di specificare se i tuoi elementi devono essere disposti in verticale o in orizzontale. Per default, il valore sarà row
, che semplicemente dispone gli elementi orizzontalmente. Puoi anche usare column
per passare all’orientamento medio.
.container { display: flex; flex-direction: row; }
Tenete a mente che l’uso di column
può influenzare l’aspetto delle altre proprietà flexbox sui vostri elementi, e per semplicità parleremo principalmente di elementi orizzontali perché questo è di gran lunga il caso d’uso più comune, ma tenete a mente che questa altra opzione di direzione esiste.
Flex-wrap
Flex-wrap definisce se gli elementi devono essere forzati a stare in una singola linea (no-wrap
, il comportamento predefinito) o se devono mantenere la loro dimensione normale conwrap
. La maggior parte delle volte vorrete il comportamento di default, ma sovrascrivere questa proprietà vi permetterà di usare le altre proprietà di flexbox senza influenzare le larghezze.
.container { display: flex; flex-wrap: wrap; }
Quando impostato su no-wrap
, gli elementi saranno ancora dimensionati in modo proporzionale gli uni agli altri.Per esempio, immaginate che gli elementi di una lista siano impostati per essere 100px
larghi, tranne l’ultimo che è 200px
. Gli elementi si ridimensioneranno per adattarsi al contenitore, ma l’ultimo elemento sarà ancora due volte più largo degli altri.
Justify-content
Justify-content determina come inserire il contenuto nella riga o nella colonna.Il valore predefinito è flex-start
, che allineerà a sinistra gli elementi. Naturalmente, abbiamo anche flex-end
per allineare a destra gli elementi e center
per centrarli.Le cose si fanno più interessanti con space-between
, che danno uguale spazio tra gli elementi ma non alle estremità, mentre space-around
dà uguale spazio anche alle estremità.
.container { display: flex; justify-content: center; }
Questo è meglio usato quando gli elementi hanno larghezze impostate (o hanno raggiunto la loro larghezza massima).
Questo può essere molto utile quando si allineano gli elementi di flexbox alla griglia, senza fare affidamento su cose come i float.
Align-content
Align-content è simile a justify-content
, ma controlla dove gli elementi sono sull’asse trasversale. Dico “altro” perché quando usateflex-direction: row
, allora align-items
controlla l’allineamento verticale, ma quando usate flex-direction: column
, è il contrario.
Puoi allineare gli elementi alla linea di base del testo all’interno di ogni elemento usandobaseline
. C’è anche un’opzione per rendere ogni elemento span da un’estremità dell’asse all’altra con stretch
.
.container { display: flex; align-items: center; }
Possiamo usare align-items: stretch
per risolvere il problema delle “colonne di uguale altezza” che ha afflitto i layout CSS fin dall’inizio. Potete anche impostare siajustify-content
che align-items
su center
per centrare i vostri elementi al centro del vostro contenitore, il che è molto utile per cose come le hero areas e le splash pages.
Ci sono diverse altre proprietà che sono usate meno spesso ma che potreste trovare utili.
Allinea-voci
Allinea-voci influenza le linee di contenuto e dove dovrebbero essere all’interno del loro contenitore. Puoi vedere qui sotto che gli elementi in ogni riga mantengono la loro altezza normale (a meno che tu non stia usando stretch
).
.container { display: flex; align-content: stretch; }
Qualche altra proprietà
Ci sono anche un certo numero di proprietà flexbox per gli elementi nel contenitore.Queste sono un po’ più facili da capire rispetto alle proprietà dei genitori e, fortunatamente, c’è un’utile stenografia che possiamo usare per rendere tutto più facile.
.list-item { flex: <flex-grow> <flex-shrink> <flex-basis>; }
-
flex-grow: <integer>
: Questo fornisce un altro modo per dare ai vostri elementi flex larghezze diverse. Se impostate tutti i vostri elementi figli suflex-grow: 1
, ma impostate l’ultimo figlio suflex-grow: 2
, sarà largo il doppio dei suoi fratelli. -
flex-shrink: <number>
: determina come l’elemento si ridurrà quando il contenitore non è abbastanza largo perché gli elementi mantengano la loro larghezza naturale. Se l’ultimo elemento è impostato suflex-shrink: 2
mentre i suoi fratelli sono impostati suflex-shrink: 1
, si restringerà il doppio dei suoi fratelli. -
flex-basis: <size>
: Ciò che dovremmo considerare essere la dimensione naturale dell’elemento. Questo può essere pensato come il “punto di rottura” al quale le proprietà di crescita e contrazione sono attivate.
Order controlla l’ordine in cui l’elemento appare nel contenitore. I numeri negativi sono accettati e appariranno prima di quello che normalmente sarebbe il primo elemento.
Align-self ha tutte le stesse opzioni di align-items
, ma permette di controllare come i singoli elementi sono allineati. Per esempio, i fratelli possono essere impostati suflex-start
, ma potete scegliere un elemento da impostare su flex-end
.
Probabilmente non li userete tutti insieme, ma una tale mostruosità assomiglierebbe a questa:
.container { align-items: flex-start; display: flex; height: 40em; } .item { flex: 1 1 2em; } .item:nth-child(3) { align-self: flex-end; flex: 2 10 5em; order: -1; }
Risorse per imparare
Flexbox può essere una cosa difficile da capire, specialmente se siete abituati alle stranezze dei layout CSS tradizionali. Siti come Codepen sono un buon modo per imparare è semplicemente sperimentare e vedere cosa si può ottenere.
Se non siete sicuri di come potreste usare flexbox in un’applicazione del mondo reale, Solved by Flexbox è una grande risorsa messa insieme da Mozilla che presenta molte grandi idee pratiche.
Position
Positioning ci dà un metodo di layout completamente diverso. Il valore predefinito è static
, e fa comportare l’elemento normalmente.
Utilizzando position: relative
è possibile specificare un offset con top
bottom
left
, e right
.
.logo { position: relative; left: 1em; top: 1em; }
Questo può essere utile per fare un semplice offset senza usare qualcosa come margin
, ma diventa davvero potente quando contiene un bambino con position:absolute
.
Posizione assoluta
Il posizionamento assoluto basa la posizione degli elementi rispetto all’elemento padre più vicino che ha position: relative
impostato. Se non ne trova uno, sarà relativo al documento.
.hero { position: relative; } .hero-icon { position: absolute; left: 20px; top: 10%; }
Il posizionamento assoluto non dovrebbe essere usato per disporre colonne di contenuto. Poiché gli elementi vengono rimossi dal flusso del documento, ciò significa che ogni volta che si aggiunge del contenuto a una sezione, potrebbe essere necessario regolare le dimensioni delle altre sezioni a mano, e questo rende il responsive design molto più di una seccatura di quanto non sia necessario.Riservate il posizionamento assoluto per ottenere quei piccoli elementi di design esattamente dove volete che siano. Come regola generale, se un elemento può essere posizionato semplicemente usando i float o una modifica agli stili display
, è probabilmente meglio evitare il posizionamento assoluto.
Centrare usando la posizione assoluta
Qualcosa che può essere molto utile ma che blocca molti principianti è centrare gli elementi con il posizionamento assoluto. Se il vostro elemento ha una dimensione impostata, è solo una questione di compensazione con i margini. Prendiamo l’ultimo esempio ma centriamo l’icona sia orizzontalmente che verticalmente. Per centrare un elemento usando il posizionamento assoluto, basta seguire questi passi:
- Aggiungi
left: 50%
all’elemento che vuoi centrare. Noterete che questo allinea il bordo sinistro dell’elemento figlio con la linea del 50% del genitore. - Aggiungi un margine sinistro negativo che è uguale alla metà della larghezza dell’elemento.Questo ci sposta indietro sul segno di metà.
- Prossimo, faremo un processo simile per l’asse verticale. Aggiungete
top: 50%
al bambino - e poi aggiungete un margine superiore negativo pari alla metà della sua altezza.
Questo significa che anche se il contenitore può cambiare dimensioni, l’elemento centrato rimarrà proprio dove vogliamo. Il CSS risultante dovrebbe assomigliare a questo:
.container { position: relative; } .centered-element { height: 100px; width: 100px; position: absolute; left: 50%; margin-left: -50px; top: 50%; margin-top: -50px; }
Posizione fissa
Il posizionamento fisso funziona come absolute
, ma è sempre relativo alviewport piuttosto che al documento e rimarrà in posizione quando gli utenti scorrono. Questo può far sentire la vostra app più come un’applicazione nativa, con un’intestazione fissa o una navigazione laterale, o per qualsiasi elemento che volete tenere a portata di mano. Come per il posizionamento assoluto, gli elementi fissi saranno rimossi dal flusso del documento, quindi potrebbe essere necessario aggiungere un padding su un elemento sottostante per assicurarsi che gli altri contenuti siano ancora visibili.
Sticky position
Il posizionamento sticky è il più nuovo del gruppo. Ci sono alcuni grandi articoli su come usarlo, così come le alternative javascript.Questo non dovrebbe essere confuso con la sempre popolare tecnica dello sticky footer, che merita anch’essa una menzione speciale.
Z-index
La proprietà position ci dà il vantaggio di poter specificare loz-index dei nostri elementi. Se torniamo alla nostra metafora di vedere gli elementi come pezzi di carta, impostare la proprietà z-index
ci permette di specificare se il nostro foglio è sopra o sotto gli altri pezzi. Un numero più alto apparirà sopra, e un numero più alto apparirà sotto. Potete anche usare un numero negativo, che può far apparire l’elemento dietro il genitore (o anche dietro il documento interamente)! Questo può portare ad una sorta di corsa agli armamenti con numeri sempre più alti per assicurarsi che un elemento sia sempre in cima. Questo può diventare piuttosto ingestibile ed è meglio usare il posizionamento e gli indici z in modo conservativo.
Floats
I floats sono la tecnica di layout più comunemente usata nei CSS, ma possono essere frustranti se non si sa come influenzano gli elementi vicini. Quando stili un elemento con float: left
, gli elementi seguenti rifluiranno, il flusso del documento è solo l’ordine del contenuto e come gli elementi si dispongono l’uno intorno all’altro. Se l’elemento flottante non ha una larghezza fissa, collasserà alla larghezza del contenuto. Se l’elemento seguente è più stretto dello spazio rimanente, si sposterà a destra. Tenete a mente che gli elementi impostati su display: block
dovranno avere una larghezza impostata o rimarranno sulla propria linea.
Potete evitare che un elemento collassi dandogli una proprietà clear
nel vostro foglio di stile. Le opzioni includono clear: both
clear: left
(che permetterà ancora il riflusso degli elementi che seguono con float: right
), e clear: right
(che fa il contrario). Potete anche usare clear: none
per sovrascrivere il comportamento predefinito.
Perché i figli fluttuanti faranno collassare i loro elementi genitori, sarete tentati di creare nuovi elementi solo per aggiungere clear: both
ed evitare questo comportamento. Anche se questo funziona, vogliamo mantenere il nostro markupsemantico quindi questo dovrebbe essere fatto solo usando i CSS se possibile. Usando uno::after
pseudo-elemento, si può creare un clearfix:
.container::after { clear: both; content: ""; display: table; }
Utilizzando un preprocessore come Bourbon è facile aggiungere questo come Sass mixin:
.container { @include clearfix; }
I float funzionano meglio per i grandi contenitori, ma potrebbero non funzionare così bene per gli elementi di testo poiché sarà difficile allinearli. Potreste scoprire che usare display:inline-block
è meglio per queste situazioni.