Questa è la traduzione dell'articolo Faux Absolute Positioning di Eric Sol pubblicato originariamente su A List Apart il 17 Giugno 2008. La traduzione viene qui presentata con il consenso dell'editore e dell'autore.
Ci sono due approcci comuni nel posizionamento con i CSS: l'uso dei float e del posizionamento assoluto.Entrambi gli approcci hanno i loro pro e contro. Insieme ai miei colleghi abbiamo sviluppato un nuovo metodo in grado di darci il meglio di questi due mondi. Dopo un po' di esperimenti
e di test, è il momento di condividere questa tecnica con tutti e vedere come possiamo lavorare insieme per migliorarla. Ho deciso di chiamarla "falso posizionamento assoluto" (faux absolute positioning) per via della tecnica delle false colonne che simula la presenza di una colonna.
Perché un'altra tecnica
Molti design di siti web sono basati su un layout a colonne con un header e un footer. Con i layout basati sul posizionamento assoluto è quasi impossibile posizionare il footer se le colonne possono crescere verticalmente. Con i layout basati sul float cambiamenti inaspettati nel contenuto possono far sì che intere colonne perdano la loro posizione, come descritto da Shaun Inman in Clearance. Tutto ciò è un effetto indesiderato e difficile da controllare su Internet Explorer per via del trattamento problematico della proprietà width
su questo browser.
Il nostro caso d'uso era ancora più complesso: il mio team stava sviluppando un generatore di form WYSIWYG che consente all'utente di trascinare degli oggetti in posizioni arbitrarie su una canvas. Avevamo bisogno di consentire agli utenti di creare dei form accattivanti che non usassero layout statici e lasciare che potessero allineare le colonne come necessario.
Per esempio, supponiamo che vogliamo un form che metta i campi dedicati al codice postale e alla città sulla stessa riga perché semanticamente collegati. Per ottenere questo risultato abbiamo provato a usare un posizionamento basato su float ispirato alla tecnica descritta in Holy Grail technique. Usando questo metodo avevamo bisogno di aggiustare la larghezza, i bordi, i margini e/o il padding del campo per il codice postale per fissare il campo della città su una posizione orizzontale stabilita e fissa. Era un problema, perché se la larghezza del campo del codice postale doveva essere aggiustata, o se volevamo aggiustare l'ammontare di spazio bianco tra i campi, il campo della città doveva essere spostato di conseguenza. Più elementi sono presenti su una pagina -più celle abbiamo nella nostra griglia- più diviene problematico questo tipo di aggiustamento. Inoltre, il posizionamento con float è sensibile al più piccolo cambiamento in diversi parametri, cosa che rende pressoché impossibile il controllo nel caso di campi di form dinamici.
In seguito abbiamo provato ad usare il posizionamento assoluto. Abbiamo ottenuto un controllo maggiore sul posizionamento dei vari oggetti ed è un metodo robusto. Ma gli elementi posizionati assolutamente non hanno altezza e ciò ha fatto sì che l'elemento contenitore (la canvas) crollasse. Ciò ha reso difficile posizionare il contenuto senza dover rendere tutto posizionato assolutamente, cosa che è impossibile da ottenere con del contenuto dinamico.
Un approccio differente
Alla fine abbiamo provato una soluzione basata sulla scoperta di un modo per calcolare lo spostamento a sinistra a partire da una posizione fissa, l'opposto rispetto a calcolarlo dal lato sinistro dell'elemento precedente. Abbiamo cercato di ottenere il tutto attraverso una combinazione di position: relative
, left: 100%
e un valore negativo per margin-left
.
Il nostro metodo parte realizzando una griglia di righe ed item. Possiamo piazzare un numero qualsiasi di item su una riga e un numero qualsiasi di righe nell'elemento contenitore:
<div id="canvas">
<div class="line">
<div class="item" id="item1">
<div class="sap-content">content here</div>
</div>
</div>
</div>
...e così via. Ogni item ha un div extra con classe "sap-content
" che svolge diverse funzioni:
- previene il bug del redraw su IE6;
- ci dà l'opportunità di avere una maggiore flessibilità per aggiungere del padding;
- ci consente di giocare con
position: overflow
(senza rompere la griglia!).
Il CSS generico applicato a questi elementi è il seguente:
.line {
float: left;
width: 100%;
display: block;
position: relative;
}
.item {
position: relative;
float: left;
left: 100%;
}
Per posizionare un elemento particolare abbiamo solo bisogno di assegnargli un valore negativo per margin-left
e una larghezza con width
. Per esempio:
item1 {
margin-left: -100%;
width: 30%;
}
Con qualche tocco extra di stili, giusto per dimostrare il funzionamento, il tutto appare così, come nell'immagine qui sotto:
Il CSS generico posiziona ogni elemento sul lato destro della canvas, con la larghezza di ciscuno basata sul suo contenuto e tutti gli elementi floattati nella loro posizione in base all'ordine con cui sono inseriti nel markup HTML. Il margin-left
è ora spostato dal lato destro della canvas invece che dall'elemento alla sua sinistra.
Vantaggi
Con il falso posizionamento assoluto possiamo allineare ogni elemento ad una posizione predefinita sulla griglia (come con il posizionamento assoluto) ma gli elementi stessi continuano ad avere effetti sul flusso normale e, grazie al clear
, hanno molti degli stessi vantaggi degli elementi immersi nel flusso normale. Ogni riga nella griglia avrà sempre un'altezza dipendente dal contenuto oppure come definita nel CSS e occuperà sempre una larghezza pari al 100%, a prescindere dal numero di colonne definite nella riga. Inoltre, possiamo evitare di usare grandi valori per margini e padding per aggiustare l'ammontare di spazio bianco tra gli elementi, cosa che è un vantaggio extra dal momento che le tecniche tradizionali richiedono l'adozione di hack specifici per IE6 per compensare i bug di questo browser nella gestione del box model.
Un altro vantaggio della tecnica è che mitiga di molto la fragilità intrinseca dei float. Quando il contenuto di un box floattato è più ampio del box stesso, esso spinge il box successivo sulla destra (e di conseguenza il box si sposta sempre giù). Con il falso posizionamento assoluto, il box alla destra rimane sempre al suo posto. Il contenuto dei box può sovrapporsi (dipende dal altri variabili come overflow: hidden
), ma questo è tutto, e secondo noi è meglio rischiare una sovrapposizione che rischiare di rompere tutto il layout.
Onestamente, sono rimasto un po' sorpreso dal fatto che la tecnica funzionasse così bene. Usa HTML 4.01 e CSS 2.1 validi, i margini sinistri negativi sono ben supportati dai browser. E c'è un'altra buona notizia: funziona con layout fissi e liquidi, può essere combinata con le colonne di uguale altezza (anche se rimangono problemi con questa soluzione), c'è la possibilità di combinare colonne a larghezza fissa e a larghezza flessibile (si consideri l'esempio che vedremo più avanti). È anche possibile usare il falso posizionamento assoluto in maniera ricorsiva, per esempio usare un elemento posizionato come container per nuove righe ed elementi.
Svantaggi
Il falso posizionamento assoluto è ispirato dai design basati su griglia e per essi è concepito. Inoltre, va molto bene per layout molto complessi. Se avete bisogno di un layout a due colonne con larghezza fissa potrebbe non essere la tecnica che fa per voi.
C'è da aggiungere che non funzionerà in ogni situazione. Se volete allineare elementi sulla sinistra non potete usare un'unità di misura che sia differente da quella usata per definire la larghezza della canvas perché non potete calcolare lo spostamento. Per esempio, se avete una canvas con larghezza pari a width: 800px
e volete uno spostamento a sinistra di 2em non potete calcolare il margin-left
perché non potete sapere quanti em stanno in 800px.
E dal momento che è una nuova tecnica che non è stata ancora testata da migliaia di utenti, dovrebbe essere considerata sperimentale perché potrebbero venir fuori risultati inaspettati in certe combinazioni di markup, CSS e browser.
Un'altra questione: quando un elemento più largo della canvas precede altri elementi nell'ordine nel codice HTML gli elementi sulla stessa fila saranno spinti verso destra per un ammontare di spazio pari alla differenza in larghezza tra il primo elemento e l'elemento canvas.
Esempi
Il primo esempio è un layout a tre colonne liquido con colonne laterali a larghezza fissa, come quello della tecnica Holy Grail. Ho implementato questo layout come template per Drupal, un popolare CMS open source. Ci sono alcune cose da notare:
- Le colonne a sinistra e destra hanno larghezza in pixel. Dunque, non possiamo calcolare il
margin-left
per il contenuto principale perché non conosciamo la larghezza della canvas e o la larghezza della colonna sinistra come percentuale della canvas. La soluzione è simile a quella di Holy Grail: posizionare la parte con il contenuto principale conmargin-left: -100%
e conwidth: 100%
, quindi aggiungere del padding per fornire lo spazio necessario alle colonne. - Le colonne sinistra, destra e principale sono rese sullo stesso livello gerarchico, così potremmo avere bisogno di qualcosa come
z-index: 100
sulle colonne. - Il padding sulle colonne sinistra e destra è aggiunto al div con classe
sap-content
aggiunto come extra; ciò mantiene semplici i nostri calcoli dandoci molta flessibilità.
Il secondo esempio è un layout liquido a cinque colonne in cui la canvas, le file e gli item sono calcolati in percentuale. L'aggiunta di immagini, bordi e padding non ha effetti sul posizionamento complessivo, anche per immagini che sono più grandi dell'elemento contenitore, come è dimostrato con l'antica mappa della città di Maastricht presente nell'esempio.
Niente hack!
Il nostro approccio non richiede hack e funziona in tutti i browser moderni (Safari, Opera, Firefox, IE7), così come su IE6 e anche su IE5.5 Win. Non funziona su IE5 Mac.
È anche molto stabile, dal momento che gli elementi, se necessario, crescono in altezza verticalmente e il layout non si rompe quando un'immagine è più grande di un elemento, per esempio. Il posizionamento degli item è indipendente dall'ordine definito nel sorgente HTML.
Sono davvero entusiasta di questo approccio e vedo molte opportunità. Liberi di provarlo, sperimentare e commentare.