CSS table, struttura base per il layout di una tipica app mobile

Sono serviti diversi anni per far abbandonare agli sviluppatori web le tabelle come strumento di creazione dei layout in favore di elementi semanticamente più rilevanti combinati con il CSS, ma il brutto effetto collaterale che ha avuto la campagna di sensibilizzazione verso la costruzione di layout flessibili con i fogli di stile è stata la completa demonizzazione delle tabelle HTML e delle stesse proprietà CSS che permettono di avvalersi dei loro potenti algoritmi di calcolo delle dimensioni.

Mi capita sempre più spesso di imbattermi in strutture tabellari formattate a mezzo di div, p, span e altri tag testuali con l’uso di strutture CSS a larghezze fisse, che sarebbero state ottenute in maniera molto più semplice (ed efficace in ottica responsive) usando il buon vecchio tag table perfettamente lecito in tale contesto.

Questa paura radicata dell’uso delle tabelle ormai viste come uno strumento desueto del passato può farci perdere di vista le grandi potenzialità che le CSS table hanno anche in relazione alle nuovissime frontiere del web quali le mobile webapp, sia native con tecnologia PhoneGap che non.

I tre elementi verticali di un layout mobile

mobile-layoutGeneralmente il layout di un’applicazione mobile si compone delle seguenti parti principali disposte verticalmente in quest’ordine :

  1. Header
  2. Contenuti
  3. Comandi

L’Header contiene il logo ed il nome dell’app o della vista corrente ed uno o più tasti interattivi. Questa zona inoltre può contenere ulteriori righe di elementi che spingono ulteriormente verso il basso il box dei Contenuti.

La parte dei Comandi può non essere sempre presente in iOS e Windows Phone, mentre in Android è possibile trovarli in questa zona ma generalmente vengono posizionati nella riga sotto l’Header.

La parte centrale dei contenuti ospita di volta in volta gli elementi pertinenti alla vista selezionata ed è scrollabile verticalmente indipendentemente dagli elementi circostanti, tuttavia l’altezza del box dei Cotenuti si deve adattare per rientrare tra i due elementi senza mandare fuori schermo nessuno dei tre.

Questo comportamento si ottiene facilmente e in maniera crossbrowser con il seguente HTML :

ed il seguente SASS/CSS :

I due elementi .layout-top e .layout-bottom, aventi rispettivamente le proprietà display:<strong>table-header-group</strong> e display:<strong>table-footer-group</strong> fanno in modo che la propria altezza sia determinata dai loro contenuti, se assenti gli elementi collassano lasciando lo spazio all’elemento centrale  .layout-middle avente display:<strong>table</strong> come il padre principale e la direttiva height:100%.

Inoltre la proprietà position è impostata su relative, questo perchè i contenuti saranno ospitati da due div interni, il primo dei quali .outWrap in position:absolute per fare in modo che occupi verticalmente sempre l’altezza del suo genitore, ovvero la riga dinamica .layout-middle in display:table, mentre il div interno .inWrap si espanderà verticalmente in maniera normale, solo che quando i contenuti eccederanno in altezza lo spazio di  .layout-middle si avrà lo scrolling all’interno di  .outWrap in modo da non intaccare il resto della struttura.

Internet Explorer Legacy

Volendo applicare questa questa struttura HTML/CSS in ambito desktop la punta dolente è naturalmente Internet Explorer, nello specifico la struttura funziona egregiamente anche in IE8, che è la versione più aggiornata disponibile sui vetusti sistemi che operano con Window XP (dismesso per la gioia di tutti l’8 aprile 2014), con la seguente modifica CSS :

La versione più problematica è invece IE9 che, nonostante la seguente fix CSS, presenta un comportamento anomalo :

L’altezza computata risulta zero nonostante visivamente l’elemento occupi tutta l’altezza disponibile

Nello specifico vedremo che l’area azzurra dei Contenuti di  .layout-middle si espande correttamente in altezza ma nessun contenuto appare all’interno. Il problema è causato dalla computazione dell’altezza dell’elemento a livello di box-model, nonostante l’altezza dichiarata 100% sull’elemento per espandersi entro tutto lo spazio verticale disponibile tra i due fratelli, che viene rispettata a livello visivo, il valore computato per l’altezza mostrata dall’inspector risulta 0.

In questo modo si spezza la catena di propagazione delle altezze dinamiche verso i suoi figli, dato che l’elemento  .outWrap in position:absolute avrà come riferimento zero e di conseguenza non sarà disegnato sullo schermo.

Tuttavia richiedendo l’altezza dell’elemento via JavaScript otteniamo il valore corretto, per cui l’unico work-around per questo strano comportamento è “propagare” via JavaScript l’altezza di  .layout-middle applicandola ad  .outWrap.

In questo modo la struttura nel complesso continua ad essere governata dal meccanismo CSS reflow.

I tre elementi orizzontali di un header mobile

mobile-app-headerAvendo messo in piedi la struttura generale scendiamo ora nel dettaglio dell’interfaccia per realizzare gli elementi orizzontali. Sia per iOS che Android troviamo una struttura molto simile composta da tre elementi principali :

  1. Tasto menu/indietro a sinistra
  2. Nome dell’app/vista corrente centrale
  3. Uno o più tasti di interazione a destra

A livello di struttura la situazione è simile alla precedente, il primo elemento a sinistra ha tendenzialmente una larghezza fissa, mentre l’area dei pulsanti a destra ha una larghezza variabile a seconda del numero di elementi che contiene, la zona centrale invece è a larghezza elastica ed occupa tutto lo spazio tra i due elementi fratelli.

La struttura HTML necessaria è simile alla precedente :

La differenza sta nel CSS, il contenitore principale #top-bar con display:table avrà come proprietà table-layout:auto in modo da consentire agli elementi figli in display:table-cell di adattarsi in base alla larghezza dei propri contenuti.

L’elemento centrale .top-bar-middle conterrà un’ulteriore struttura di div per consentire il corretto centramento verticale e contenimento orizzontale dei contenuti tramite position:absolute, in modo che la dimensione sia dettata dal padre in display:table-cell. Questo permetterà agli elementi testuali al suo interno aventi text-overflow:ellipsis di non eccedere mai il contenitore centrale e di non influenzare gli elementi circostanti.

La width:1% applicata all’elemento .top-bar-right serve a limitare la larghezza rispetto ai contenuti interni, i quali se disposti come tag separati dovranno avere impostato display:table-cell per poter essere affiancati orizzontalmente.

In questo frangente non sono necessari accorgimenti JavaScript di alcun tipo in quanto le larghezze vengono calcolate senza problemi nei vari browser.

La barra dei comandi in basso allo schermo

Realizzare la barra dei comandi è relativamente semplice, sia in iOS che Android gli elementi che la compogono hanno una larghezza variabile che equivale alla larghezza del contenitore padre equamente distribuita tra i suoi figli :

Combinazione delle CSS table

Il risultato finale delle tre tecniche combinate ci restituisce una struttura flessibile sia in altezza che in larghezza, in cui i contenuti posso essere modificati di dimensione e numero senza rischiare di rompere nulla. Inoltre così facendo evitiamo di usare il position:fixed notoriamente instabile in diversi frangenti sui dispositivi mobili, e ci assicuriamo che la scrollbar dei contenuti corrisponda esattamente all’area dei contenuti stessi e non si estenda al resto della pagina.

https://sresc.io/1c

2 thoughts on “CSS table, struttura base per il layout di una tipica app mobile”

    1. Ciao Luca,
      grazie per la segnalazione, ho fatto delle prove e in effetti Safari 10 tratta diversamente due aspetti del CSS:

      1. .outWrap: l’elemento interno non necessità più di essere in position:static ma richiede relative come in tutti gli altri browser, ho aggiunto una regola che annulla solo su fari questo ovveride fatto a livello generale per webkit sopratutto per i device Android, potrebbe essere migliorato ulteriormente sapendo esattamente quali versioni ne hanno bisogno, avendo evidenza solo di Safari 10 come eccezione credo per ora sia accettabile
      2. .layout-middle: nel ripristinare il posizionamento dell’elemento di cui sopra, il genitore ovvero l’elemento centrale in display:table ora necessità di avere un’altezza minima impostata, 1px è sufficiente per far scattare il calcolo corretto dell’altezza

      Riassumendo le aggiunte sono le seguenti :

      Ho aggiornato sia gli snippet della pagina che gli esempi live su CodePen

      Per il “tasto commento” ti riferisci invece al layout del blog? Puoi postarmi uno screenshot?

Lascia un commento

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.