Rendere mobile il tuo sito HTML5

Introduzione

Lo sviluppo per il web mobile è un tema caldo di questi tempi. Quest'anno, per la prima volta in assoluto, gli smartphone hanno superato i PC in termini di vendite. Sempre più utenti utilizzano un dispositivo mobile per navigare sul web, il che significa che per gli sviluppatori è diventato fondamentale ottimizzare i propri siti per i browser mobile.

Il campo di battaglia "mobile" è ancora un territorio inesplorato per un gran numero di sviluppatori. Molte persone hanno siti legacy esistenti che trascurano completamente gli utenti di dispositivi mobili. Il sito è stato progettato principalmente per la navigazione da computer e ha un degrado scarso nei browser mobile. Questo sito (html5rocks.com) non fa eccezione. Al momento del lancio, abbiamo dedicato poco impegno alla realizzazione di una versione mobile del sito.

Creazione di un sito html5rocks.com ottimizzato per il mobile

Come esercizio, ho pensato che sarebbe stato interessante prendere html5rocks (un sito HTML5 esistente) e migliorarlo con una versione ottimizzata per il mobile. La mia preoccupazione principale riguardava la quantità minima di lavoro necessaria per scegliere come target gli smartphone. L'obiettivo del mio esercizio non era creare un sito mobile completamente nuovo e gestire due basi di codice. Ci sarebbe voluto un'eternità e sarebbe stato un enorme spreco di tempo. Avevamo già definito la struttura del sito (markup). Abbiamo dato un'occhiata al CSS. La funzionalità di base (JS) era presente. Il punto è che molti siti si trovano nella stessa situazione.

Questo articolo illustra come abbiamo creato una versione mobile di html5rocks ottimizzata per i dispositivi Android e iOS. Basta caricare html5rocks.com su un dispositivo che supporta uno di questi sistemi operativi per vedere la differenza. Non ci sono reindirizzamenti a m.html5rocks.com o altre sciocchezze di questo tipo. Puoi utilizzare html5rocks così com'è, con il vantaggio aggiuntivo di un'esperienza visiva e di utilizzo ottimali su un dispositivo mobile.

html5rocks.com per computer html5rocks.com mobile
html5rocks.com su computer (a sinistra) e dispositivo mobile (a destra)

Query supporti CSS

HTML4 e CSS2 supportano i stylesheet dipendenti dai media da un po' di tempo. Ad esempio:

<link rel="stylesheet" media="print" href="printer.css">

ha come target i dispositivi di stampa e fornisce uno stile specifico per i contenuti della pagina quando vengono stampati. CSS3 fa un passo avanti rispetto all'idea dei tipi di media e ne migliora la funzionalità con le query sui media. Le query sui media estendono l'utilità dei tipi di media consentendo un'etichettatura più precisa degli stili. In questo modo, la presentazione dei contenuti può essere personalizzata in base a un determinato intervallo di dispositivi di output senza dover modificare i contenuti stessi. Sembra perfetto per un layout esistente che deve essere modificato.

Puoi utilizzare le query sui media nell'attributo media dei fogli di stile esterni per scegliere come target la larghezza dello schermo, la larghezza del dispositivo, l'orientamento e così via. Per l'elenco completo, consulta la specifica delle query sui media del W3C.

Targeting per dimensioni dello schermo

Nel seguente esempio, phone.css si applica ai dispositivi che il browser considera "da mano" o con schermi di larghezza <= 320 px.

 <link rel='stylesheet'
  media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>

Se anteponi una query sui media con la parola chiave "only", i browser non conformi a CSS3 ignoreranno la regola.

Di seguito è riportato il targeting per le dimensioni dello schermo comprese tra 641 e 800 pixel:

 <link rel='stylesheet'
  media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>

Le query sui contenuti multimediali possono essere visualizzate anche all'interno dei tag <style> in linea. Di seguito sono riportati i tipi di media all scelti come target in caso di orientamento verticale:

 <style>
  @media only all and (orientation: portrait) { ... }
 </style>

media="handheld"

Dobbiamo fermarci un minuto e parlare di media="handheld". Il fatto è che Android e iOS ignorano media="handheld". L'affermazione è che gli utenti perderanno i contenuti di alta qualità forniti dagli stili CSS che hanno come target media="screen" e che gli sviluppatori sono meno propensi a mantenere una versione media="handheld" di qualità inferiore. Pertanto, nell'ambito del loro motto "full web", la maggior parte dei browser per smartphone moderni ignora semplicemente i fogli di stile per dispositivi mobili.

Sarebbe ideale utilizzare questa funzionalità per scegliere come target i dispositivi mobili, ma i vari browser l'hanno implementata in modi diversi:

  • Alcuni leggono solo il foglio di stile del palmare.
  • Alcuni leggono solo il foglio di stile del palmare, se presente, ma per impostazione predefinita utilizzano il foglio di stile dello schermo.
  • Alcuni leggono sia il foglio di stile del dispositivo portatile sia il foglio di stile dello schermo.
  • Alcuni leggono solo il foglio di stile dello schermo.

Opera Mini non ignora media="handheld". Il trucco per fare in modo che Windows Mobile riconosca media="handheld" è usare le lettere maiuscole per il valore dell'attributo media per lo stile foglio di stile della schermata:

 <!-- media="handheld" trick for Windows Mobile -->
 <link rel="stylesheet" href="screen.css" media="Screen">
 <link rel="stylesheet" href="mobile.css" media="handheld">

In che modo html5rocks utilizza le query sui media

Le query sui media vengono utilizzate ampiamente in html5rocks mobile. Ci hanno permesso di perfezionare il layout senza dover apportare modifiche significative al markup del nostro template Django… un vero toccasana! Inoltre, il supporto su vari browser è abbastanza buono.

Nel <head> di ogni pagina vedrai i seguenti fogli di stile:

 <link rel='stylesheet'
  media='all' href='/static/css/base.min.css' />
 <link rel='stylesheet'
  media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />

base.css ha sempre definito il look and feel principale di html5rocks.com, ma ora stiamo applicando nuovi stili (mobile.css) per larghezze dello schermo inferiori a 800 pixel. La query sui contenuti multimediali copre gli smartphone (~320 px) e l'iPad (~768 px). L'effetto: stiamo sostituendo gradualmente gli stili in base.css (solo se necessario) per migliorare l'aspetto dei contenuti sui dispositivi mobili.

Alcune delle modifiche allo stile applicate da mobile.css:

  • Riduci gli spazi vuoti/la spaziatura interna aggiuntivi nel sito. Gli schermi piccoli significano che lo spazio è prezioso.
  • Rimuove gli stati :hover. Non verranno mai visualizzati sui dispositivi touch.
  • Regola il layout in modo che sia a colonna singola. Ne parleremo più avanti.
  • Rimuove box-shadow attorno al div del contenitore principale del sito. Le ombre delle caselle di grandi dimensioni riducono il rendimento della pagina.
  • È stato utilizzato il modello di contenitore flessibile CSS box-ordinal-group per modificare l'ordine di ogni sezione nella home page. Nella home page, la sezione "IMPARA CON I GRUPPI DI FUNZIONALITÀ HTML5 DI BASE" precede la sezione "TUTORIAL", mentre nella versione mobile è posta dopo. Questo ordinamento era più adatto ai dispositivi mobili e non richiedeva modifiche al markup. Flexbox CSS FTW!
  • Rimuove le modifiche opacity. La modifica dei valori alfa influisce negativamente sul rendimento sui dispositivi mobili.

Meta tag mobile

Mobile WebKit supporta alcune funzionalità che offrono agli utenti un'esperienza di navigazione migliore su determinati dispositivi.

Impostazioni dell'area visibile

La prima impostazione meta (e quella che utilizzerai più spesso) è la proprietà viewport. L'impostazione di un'area visibile indica al browser come devono adattarsi i contenuti allo schermo del dispositivo e lo informa che il sito è ottimizzato per il mobile. Ad esempio:

 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

indica al browser di impostare l'area visibile in base alla larghezza del dispositivo con un'escursione iniziale di 1. Questo esempio consente anche lo zoom, un'opzione che può essere auspicabile per un sito web, ma non per un'app web. Potremmo impedire lo zoom con user-scalable=no o limitare la scalabilità a un determinato livello:

 <meta name=viewport
  content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

Android estende il meta tag viewport consentendo agli sviluppatori di specificare per quale risoluzione dello schermo è stato sviluppato il sito:

 <meta name="viewport" content="target-densitydpi=device-dpi">

I valori possibili per target-densitydpi sono device-dpi, high-dpi, medium-dpi, low-dpi.

Se vuoi modificare la pagina web per densità dello schermo diverse, utilizza la query supporti CSS -webkit-device-pixel-ratio e/o la proprietà window.devicePixelRatio in JavaScript, quindi imposta la proprietà meta target-densitydpi su device-dpi. In questo modo, Android non esegue la scalabilità nella pagina web e ti consente di apportare le modifiche necessarie per ogni densità tramite CSS e JavaScript.

Per ulteriori informazioni sul targeting delle risoluzioni dei dispositivi, consulta la documentazione di WebView di Android.

Navigazione a schermo intero

Esistono altri due valori meta che sono iOS-sfic. apple-mobile-web-app-capable e apple-mobile-web-app-status-bar-style mostreranno i contenuti della pagina in modalità a schermo intero simile a un'app e renderanno traslucida la barra di stato:

 <meta name="apple-mobile-web-app-capable" content="yes">
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

Per ulteriori informazioni su tutte le opzioni meta disponibili, consulta la documentazione di riferimento di Safari.

Icone della schermata Home

I dispositivi iOS e Android accettano anche rel="apple-touch-icon" (iOS) e rel="apple-touch-icon-precomposed" (Android) per i link. Quando un utente aggiunge il tuo sito ai preferiti, viene creata un'icona simile a un'app nella schermata Home:

 <link rel="apple-touch-icon"
      href="/static/images/identity/HTML5_Badge_64.png" />
 <link rel="apple-touch-icon-precomposed"
      href="/static/images/identity/HTML5_Badge_64.png" />

In che modo html5rocks utilizza i meta tag mobile

Mettendo tutto insieme, ecco uno snippet della sezione <head> di html5rocks:

 <head>
  ...
   <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />

   <link rel="apple-touch-icon"
        href="/static/images/identity/HTML5_Badge_64.png" />
   <link rel="apple-touch-icon-precomposed"
        href="/static/images/identity/HTML5_Badge_64.png" />
  ...
 </head>

Layout verticale

Su schermi più piccoli, è molto più comodo scorrere verticalmente rispetto a orizzontalmente. Per i dispositivi mobili è preferibile mantenere i contenuti in un layout verticale a una colonna. Per html5rocks, abbiamo utilizzato le query supporti CSS3 per creare un layout di questo tipo. Ancora una volta, senza modificare il markup.

Indice dei tutorial. Tutorial. Pagina Funzionalità HTML5. Pagina dei profili degli autori.
Layout verticale a una colonna in tutto il sito.

Ottimizzazioni per il mobile

La maggior parte delle ottimizzazioni che abbiamo apportato sono cose che avrebbero dovuto essere fatte in primo luogo. Ad esempio, ridurre il numero di richieste di rete, la compressione JS/CSS, il gzip (disponibile senza costi su App Engine) e ridurre al minimo le manipolazioni DOM. Queste tecniche sono best practice comuni ma a volte vengono trascurate quando si cerca di lanciare un sito in fretta.

Nascondere automaticamente la barra degli indirizzi

I browser mobile non dispongono dell'area di visualizzazione della controparte desktop. A peggiorare le cose, su piattaforme diverse, a volte ti ritrovi con una grande barra degli indirizzi nella parte superiore dello schermo… anche dopo il caricamento della pagina.

Un modo semplice per risolvere il problema è scorrere la pagina utilizzando JavaScript. Anche se lo fai di un solo pixel, la fastidiosa barra degli indirizzi verrà rimossa. Per nascondere forzatamente la barra degli indirizzi su html5rocks, ho collegato un gestore di eventi onload all'oggetto window e ho fatto scorrere la pagina verticalmente di un pixel:

Barra degli indirizzi.
La barra degli indirizzi brutta occupa spazio sullo schermo.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

Abbiamo anche inserito questo ascoltatore nella nostra variabile di modello is_mobile poiché non è necessario su computer.

Riduci le richieste di rete, risparmia larghezza di banda

È noto che ridurre il numero di richieste HTTP può migliorare notevolmente le prestazioni. I dispositivi mobili limitano ulteriormente il numero di connessioni contemporaneamente che il browser può effettuare, pertanto i siti mobile trarranno ancora più vantaggio dalla riduzione di queste richieste estranee. Inoltre, è fondamentale risparmiare ogni byte perché la larghezza di banda è spesso limitata sugli smartphone. Potresti far pagare gli utenti.

Di seguito sono riportati alcuni degli approcci che abbiamo adottato per ridurre al minimo le richieste di rete e la larghezza di banda su html5rocks:

  • Rimuovi gli iframe, che sono lenti. Gran parte della nostra latenza proveniva da widget di condivisione di terze parti (Buzz, Google Friend Connect, Twitter, Facebook) nelle pagine dei tutorial. Queste API sono state incluse tramite i tag <script> e creano iframe che riducono la velocità della pagina. I widget sono stati rimossi per i dispositivi mobili.

  • display:none: in alcuni casi, il markup veniva nascosto se non era adatto al profilo mobile. Un buon esempio sono le quattro caselle arrotondate nella parte superiore della home page:

Pulsanti delle caselle nella home page.
Pulsanti delle caselle nella home page.

Non sono presenti sul sito mobile. È importante ricordare che il browser invia comunque una richiesta per ogni icona, nonostante il relativo contenitore sia nascosto con display:none. Pertanto, non è stato sufficiente nascondere questi pulsanti. Non solo si spreca la larghezza di banda, ma l'utente non ne vedrebbe nemmeno i risultati. La soluzione è stata creare un valore booleano "is_mobile" nel nostro modello Django per omettere selettivamente sezioni di HTML. Quando l'utente visualizza il sito su uno smart device, i pulsanti non vengono visualizzati.

  • Cache dell'applicazione: non solo ci offre il supporto offline, ma consente anche un avvio più rapido.

  • Compressione CSS/JS: utilizziamo YUI Compressor anziché Closure Compiler principalmente perché gestisce sia CSS che JS. Abbiamo riscontrato un problema con le query sui media in linea (query sui media visualizzate all'interno di un foglio di stile) in YUI compressor 2.4.2 (vedi questo problema). Il problema è stato risolto utilizzando YUI Compressor 2.4.4 o versioni successive.

  • Se possibile, utilizza gli sprite di immagini CSS.

  • È stato utilizzato pngcrush per la compressione delle immagini.

  • Sono stati utilizzati dataURI per le immagini di piccole dimensioni. La codifica Base64 aggiunge circa il 30%in più di dimensioni all'immagine, ma salva la richiesta di rete.

  • Carica automatico di Ricerca Google personalizzata utilizzando un singolo tag script anziché caricarlo dinamicamente con google.load(). Quest'ultimo effettua una richiesta aggiuntiva.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • La nostra stampante di codice leggibile e Modernizr erano inclusi in ogni pagina, anche se non sono mai stati utilizzati. Modernizr è fantastico, ma esegue una serie di test a ogni caricamento. Alcuni di questi test apportano modifiche costose al DOM e rallentano il caricamento della pagina. Ora includiamo queste librerie solo nelle pagine in cui sono effettivamente necessarie. -2 richieste :)

Ulteriori ottimizzazioni delle prestazioni:

  • È stato spostato tutto il codice JS nella parte inferiore della pagina (ove possibile).
  • Sono stati rimossi i tag <style> in linea.
  • Ricerche DOM memorizzate nella cache e manipolazioni DOM ridotte al minimo: ogni volta che tocchi il DOM, il browser esegue un riflusso. I ricollegamenti sono ancora più costosi su un dispositivo mobile.
  • È stato trasferito al server il codice lato client inutilizzato. Nello specifico, il controllo consente di impostare lo stile di navigazione della pagina corrente:js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
  • Gli elementi con larghezze fisse sono stati sostituiti con width:100% o width:auto fluidi.

Cache applicazione

La versione mobile di html5rocks utilizza la cache dell'applicazione per velocizzare il caricamento iniziale e consente agli utenti di leggere i contenuti offline.

Quando implementi AppCache sul tuo sito, è molto importante non memorizzare nella cache il file manifest (esplicitamente nel file manifest stesso o implicitamente con intestazioni di controllo della cache pesanti). Se il manifest viene memorizzato nella cache dal browser, il debug è un incubo. iOS e Android memorizzano particolarmente bene questo file nella cache, ma non forniscono un modo pratico per svuotare la cache come fanno i browser desktop.

Per evitare questa memorizzazione nella cache per il nostro sito, abbiamo prima impostato App Engine in modo da non memorizzare mai nella cache i file manifest:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

In secondo luogo, abbiamo utilizzato l'API JS per informare l'utente al termine del download di un nuovo manifest. Viene chiesto di aggiornare la pagina:

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

Per risparmiare traffico di rete, mantieni il manifest semplice. In altre parole, non indicare ogni pagina del tuo sito. Elenca solo le immagini, i file CSS e JavaScript importanti. L'ultima cosa che vuoi fare è forzare il browser mobile a scaricare un numero elevato di asset a ogni aggiornamento dell'appcache. Ricorda invece che il browser memorizza nella cache una pagina HTML in modo implicito quando l'utente la visita (e include un attributo <html manifest="...">).