Il problema si pone quando abbiamo a che fare con un layout composto da un div contenitore nel quale ci sono due div disposti in colonne affiancate: la prima colonna a sinistra (il div rosso nella foto accanto) è una sidebar di dimensioni p.e. del 30% e la seconda colonna a destra (che flotta a sinistra), è il contenitore del testo principale (il div verde).
Normalmente, per avere una pagina ben leggibile anche sui dispositivi mobili, nei quali la divisione in 2 colonne ostacolerebbe la leggibilità del testo per via delle dimensioni troppo piccole, si imposta nel foglio stile CSS una media query attiva al di sotto di una certa dimensione della finestra del browser che resetta la dimensione dei due div al 100%. In questo modo otteniamo due div disposti orizzontalmente e fin qui, tutto bene. Il problema sta nel fatto che noi vorremmo il div verde (quello a destra!) che porta il contenuto principale, sopra a quello rosso (quello a sinistra) che contiene invece informazioni secondarie o di navigazione.
Tutto sarebbe più semplice se la sidebar si trovasse a destra e dunque dopo il contenuto principale. In questo caso basterebbe solo modificare il CSS, nel nostro caso invece, è necessario farci dare un ‘aiutino’ da qualche riga di javascript.
Vediamo il codice HTML di esempio:
1 2 3 4 5 6 7 8 9 10 11 | <div id='container'> <div class='inner-sidebar'><h2>Inner sidebar</h2> <p>Lorem ipsum dolor sit amet ... </p> </div> <div class='inner-content'><h2>Inner content</h2> <p>Lorem ipsum dolor sit amet ... </p> </div> </div> |
E questo è il foglio stile associato:
1 2 3 4 5 6 7 | #container{padding:10px} .inner-sidebar{float:left;width:25%;background:#BFBFBF;padding:10px} .inner-content{float:left;width:65%;padding:10px} @media only screen and (max-width:770px) { .inner-sidebar{width:100%} .inner-content{width:100%} } |
Ora dobbiamo fare in modo che quando le dimensioni della finestra scendono al di sotto di 770px il div ‘inner-sidebar‘ viene staccato dal div ‘container‘ e inserito dopo ‘inner-content‘ e, naturalmente dobbiamo fare in modo che quando la finestra viene riportata a una larghezza maggiore di 770px tutto ritorna a posto. Vogliamo anche che tutto funzioni anche quando la finestra non viene ridimensionata ma parte naturalmente con una dimensione inferiore ai 770px.
Ecco il codice javascript (che necessita jQuery):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | $( document ).ready(function() { moveDiv(); }); $(window).resize(function() { //Fires when window is resized moveDiv(); }); function moveDiv() { var width = (window.innerWidth > 0) ? window.innerWidth : screen.width; if(width <= 770) { var detach = $("#container").find(".inner-sidebar").detach(); if ($("#container").find(".inner-content").length > 0) { $(detach).insertAfter($("#container").find(".inner-content")); } } if(width > 770) { if ($("#container").find(".inner-content").length > 0) { var detach = $("#container").find(".inner-content").detach(); $(detach).insertAfter($("#container").find(".inner-sidebar")); } } } |
La funzione moveDiv()
per prima cosa calcola la larghezza della finestra attiva, poi cerca il div da spostare, lo stacca mediante il metodo detach()
dal contenitore container e lo riposiziona dopo il div inner-content, mentre effettua l’operazione inversa se lo trova già “attaccato” al div inner-content. La funzione viene richiamata sia all’inizio, appena caricato il DOM che ogni volta che viene attraversata la soglia di larghezza che abbiamo stabilito a 770px.
Il risultato è raggiunto come potete vedere su questo esempio. Nell’esempio ho inserito anche un pulsante per abilitare / disabilitare lo script in modo che si possa apprezzare il risultato ridimensionando la finestra del browser sia con che senza lo spostamento del div.
In conclusione, con questo workaround si riesce a rendere responsive un layout che inizialmente non lo era, ma il browser farà un bel po’ di lavoro in più e tutto sommato la prossima volta suggerirei di scegliere un layout con la sidebar a destra che, come avrete capito, rende le cose molto più semplici e veloci.
Riferimenti: