Questa è la traduzione dell'articolo Dynamic resolution dependent layouts di Kevin Hale, pubblicato originariamente su Particletree il 16 novembre 2005. La traduzione viene qui presentata con il consenso dell'editore e dell'autore.
In un mio precedente articolo dedicato ai layout con i CSS, ho parlato dei diversi metodi che un web designer ha a disposizione nella realizzazione dei suoi siti web. In questo vorrei soffermarmi sull'implementazione di un layout dinamico in base alla risoluzione dello schermo: penso che possa offrire un'alternativa valida a quelli che vanno alla ricerca di un punto di equilibrio tra layout a larghezza fissa e layout liquidi.
Con i layout dinamici le possibilità sono davvero infinite. Possiamo cambiare layout a 3 colonne in layout a 2 colonne, fornire una dimensione del testo adeguata per favorire la leggibilità, possiamo anche premiare i visitatori che hanno schermi a larga o larghissima risoluzione con dei contenuti extra e con immagini più grandi. Tutto senza dover mettere PHP all'interno nei CSS o perdere i benefici in termini di cache offerti dall'uso di fogli di stile esterni.
Prima di passare a parlare del JavaScript, devo dire quanto sia stato a volte frustrante il constatare come un layout liquido non si presenti nel modo giusto alle diverse risoluzioni che gli utenti di un mio sito usano. Le colonne non si sono mai davvero adattate nel modo in cui volevo e dimensioni del testo troppo piccole alle alte risoluzioni, e che andavano bene su risoluzioni inferiori, rovinavano irrimediabilmente la leggibilità del contenuto. Quando ho provato a sacrificare i layout ottimizzati per la risoluzione 800x600, ho finito con il dare problemi a quegli utenti che non massimizzavano la finestra del loro browser.
Prima di leggere l'articolo di Man in Blue sui Layout dipendenti dalla risoluzione, pensavo che i layout fissi non sfruttassero i vantaggi del web come medium dinamico e che quelli liquidi fallissero nell'adattarsi al meglio alla varietà dei modi di visualizzaizone possibili. L'implementazione di Man in Blue è certamente un capolavoro, ma penso che possiamo creare una versione più modulare e facile da sviluppare, sia per gli sviluppatori che per i designer.
Vediamoli in azione
Ho realizzato una piccola pagina demo che mostra come un layout dinamico in base alla risoluzione possa fornire ottime soluzioni in termini di adattabilità con una struttura XHTML molto essenziale. Ecco la demo.
Provate a ridimensionare la finestra del vostro browser per vedere il layout adeguarsi di conseguenza in base alle dimensioni. La cosa positiva di questo metodo è che non bisogna ricaricare un nuovo CSS per ciascun layout. Ho solo bisogno di caricare le regole necessarie per adattare il layout di default alla larghezza della finestra del browser. Più che uno style switcher è uno style adapter.
Implementazione
Prima di proseguire, scaricate il file dynamiclayouts.zip che contiene usati nella demo appena vista.
La prima cosa che faremo è piazzare nella sezione head
tutti i fogli di stile che andremo ad usare per definire ogni layout dinamico. Ecco un esempio tratto dalla demo:
<link rel="stylesheet" type="text/css" href="css/default.css" title="default"/>
<link rel="alternate stylesheet" type="text/css" href="css/thin.css" title="thin"/>
<link rel="alternate stylesheet" type="text/css" href="css/wide.css" title="wide"/>
<link rel="alternate stylesheet" type="text/css" href="css/wider.css" title="wider"/>
Notate che abbiamo aggiunto l'attributo title
a tutti gli elementi link
e che abbiamo definito i CSS dinamici come "alternate stylesheet" nell'attributo rel
. Assicuratevi di specificare il vostro foglio di stile primario assegnando ad esso l'attributo title="default"
. Il CSS di default è usato come base per tutti i layout dinamici e se JavaScript è disabilitato sarà quello che il browser userà per mostrare la pagina. Se usate più fogli di stile per gestire la presentazione della pagina, dovrete settarli tutti come "default" per evitare che lo script li sostituisca quando il layout è modificato dinamicamente. Se volete adattare questo metodo per creare un vero e proprio style switcher, basterà rimuovere l'attributo title="default"
e lo script disabiliterà completamente il foglio di stile di base usando solo le regole contenute nei CSS alternativi.
Subito dopo possiamo inserire il file JavaScript dynamiclayout
:
<script src="scripts/dynamiclayout.js" type="text/javascript"></script>
All'interno di questo JavaScript consideriamo per un attimo la funzione dynamicLayout
(i commenti sono tradotti in italiano, n.d.t):
function dynamicLayout(){
var browserWidth = getBrowserWidth();
//Carica le regole CSS per il layout stretto
if (browserWidth < 750){
changeLayout("thin");
}
//Carica le regole CSS per il layout medio
if ((browserWidth >= 750) && (browserWidth <= 950)){
changeLayout("wide");
}
//Carica le regole CSS per il layout più largo
if (browserWidth > 950){
changeLayout("wider");
}
}
Il cuore del nostro processo è nell'identificazione della larghezza del browser nella prima riga della funzione. Useremo la funzione getBrowserWidth()
adottata da Man in Blue per aiutarci. Ecco il codice:
function getBrowserWidth(){
if (window.innerWidth){
return window.innerWidth;}
else if (document.documentElement && document.documentElement.clientWidth != 0){
return document.documentElement.clientWidth; }
else if (document.body){return document.body.clientWidth;}
return 0;
}
Per la demo, ho impostato tutto in modo tale che il sito si adatti a tre differenti risoluzioni in base alla larghezza della finestra del browser: meno di 750px, più larga di 750px (ma inferiore a 950px), più larga di 950px. Le funzioni changeLayout
che sono usate in dynamicLayout
(vedi sopra) corrispondono ai valori dell'attributo title
definiti per i nostri fogli di stile alternativi. Come si vede, è piuttosto semplice modificare a nostro piacere le condizioni if
adattando tutto alle nostre esigenze.
Ora, all'interno dei fogli di stile alternativi, dovremo definire le regole di cui abbiamo bisogno per adattare ciascun layout ad una particolare risoluzione. Le regole CSS dei fogli di stile alternativi sono applicate dopo che il caricamento del CSS di default: in questo modo sostituiranno tutte le regole che non abbiano applicato ad esse la dichiarazione !important
. È ovviamente possibile riscrivere per intero tutte le regole presenti nel CSS di base, ma spesso i layout non hanno bisogno di molte modifiche per funzionare in differenti situazioni. Nella demo, per esempio, mentre il CSS di default usa più di 10 regole per creare il design di base, il foglio di stile "thin" ha bisogno di cambiare solo poche regole e selettori per far funzionare il sito a basse risoluzioni:
/* ----- Regole CSS per il layout stretto (thin) ----- */
body{
font-size:.8em;
}
#container{
width:80%;
}
#primaryContent{
width:100%;
line-height: 125px;
}
#secondaryContent{
width:100%;
line-height: 125px;
}
Questo è uno dei punti di forza di questo metodo. Possiamo facilmente passare da layout fissi a layout liquidi in base a quella che è la situazione ottimale per l'utente e ciascun layout è contenuto nel suo proprio foglio di stile esterno: così dobbiamo solo specificare le modifiche per adattare un design ad una particolare situazione. Ciò rende tutto più facile da comprendere, più veloce da realizzare e ottimo in fase di sviluppo per via della totale separazione tra presentazione e interazione con JavaScript.
Per concludere, useremo la funzione addEvent
di John Resig per eseguire le nostre funzioni al caricamento della pagina e quando l'utente ridimensiona la finestra del suo browser:
//addEvent() by John Resig
function addEvent( obj, type, fn ){
if (obj.addEventListener){
obj.addEventListener( type, fn, false );
}
else if (obj.attachEvent){
obj["e"+type+fn] = fn;
obj[type+fn] = function(){ obj["e"+type+fn]( window.event ); }
obj.attachEvent( "on"+type, obj[type+fn] );
}
}
//Run dynamicLayout function when page loads and when it resizes.
addEvent(window, 'load', dynamicLayout);
addEvent(window, 'resize', dynamicLayout);
Se non volete far cambiare il layout al ridimensionamento della finestra, eliminate pure la seconda chiamata di addEvent
a dynamicLayout
per far sì che l'adattamento del layout avvenga solo quando la pagine viene caricata per la prima volta.
Conclusioni
Prima di terminare, vorrei spendere due parole per parlare del modo in cui questa implementazione dovrebbe essere fatta. Idealmente, dovremmo manipolare le regole CSS @import
per scegliere il foglio di stile da aggiungere in coda alla fine del CSS di default. Purtroppo, le specifiche del W3C che si occupano della gestione in JavaScript delle regole CSS sono implementate in maniera così terribile tra i diversi browser che abbiamo dovuto usare, sin dal 2001,una funzione di style switching truccata basata sulla disabilitazione degli elementi link
per riuscire a far funzionare un sistema di layout dinamici.
Via, facciamola funzionare questa magia! Io credo che la corretta implementazione nei browser delle regole CSS potrebbe abbassare di molto e per molti la barriera di ingresso verso il prossimo livello del web design: la manipolazione del DOM. Sarebbe molto più facile imparare a manipolare il livello della presentazione se potessimo usare lo stesso vocabolario per modificare il CSS via JavaScript. per esempio, come sarebbe bello essere in grado di usare una cose come questa:
var defaultSheet = document.styleSheets[0];
defaultSheet.insertRule("#container{width:500px;}");
O come questa:
totalRules = defaultSheet.cssRules.length;
lastRule = defaultSheet.cssRules[totalRules - 1];
defaultSheet.addImport("/css/wide.css", lastRule);
Peggio per noi, allora. La maggior parte della sintasi per manipolare le regole CSS è diversa in IE e nei browser Gecko-based, e Safari si rifiuta di cambiare il rendering della pagina anche se riconosce i metodi. È triste riscontare quanto tutto ciò ci impedisca di sfruttare un sacco di straordinarie opportunità e spero che la recente rinascita di JavaScript aiuterà la gente a prendere coscienza di queste limitazioni affinché possano chiedere di correggerle. Se volete leggere qualcosa in più sui problemi nell'implementazione delle regole CSS, date un'occhiata all'articolo di Peter Paul Koch sull'argomento.