Rendere mobile il tuo sito HTML5

Introduzione

Lo sviluppo per il web mobile è un argomento molto discusso di questi tempi. Quest'anno, per la prima volta in assoluto, gli smartphone hanno superato i PC. Sempre più utenti utilizzano un dispositivo mobile per navigare sul web, il che significa che sta diventando fondamentale per gli sviluppatori 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 mobile. Il sito è stato progettato principalmente per la navigazione su browser desktop e non si adatta bene ai browser mobile. Questo sito (html5rocks.com) non fa eccezione. Al momento del lancio, non abbiamo dedicato molto impegno alla versione mobile del sito.

Creare 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. Mi interessava soprattutto 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 mantenere due codebase. Ci sarebbe voluto un'eternità e sarebbe stato un enorme spreco di tempo. Avevamo già definito la struttura del sito (markup). Avevamo un aspetto e uno stile (CSS). La funzionalità di base (JS) era presente. Il punto è che molti siti si trovano nella stessa situazione.

Questo articolo esamina come abbiamo creato una versione mobile di html5rocks ottimizzata per 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 del genere. Ottieni html5rocks così com'è… con l'ulteriore vantaggio di un aspetto fantastico e un funzionamento ottimale su un dispositivo mobile.

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

Query supporti CSS

HTML4 e CSS2 supportano da tempo i fogli di stile dipendenti dai media. Ad esempio:

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

Sceglierebbe come target i dispositivi di stampa e fornirebbe uno stile specifico per i contenuti della pagina quando viene stampata. CSS3 porta l'idea dei tipi di media un passo avanti e ne migliora la funzionalità con le query supporti. Le query supporti estendono l'utilità dei tipi di supporti consentendo un'etichettatura più precisa dei fogli di stile. In questo modo, la presentazione dei contenuti può essere personalizzata per una gamma specifica di dispositivi di output senza dover modificare i contenuti stessi. Sembra perfetto per un layout esistente che deve essere modificato.

Puoi utilizzare le query supporti 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 supporti del W3C.

Targeting per dimensioni dello schermo

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

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

Se anteponi la parola chiave "only" alle query supporti, i browser non conformi a CSS3 ignoreranno la regola.

Il seguente codice ha come target le dimensioni dello schermo comprese tra 641 px e 800 px:

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

Le query supporti possono essere visualizzate anche all'interno di tag <style> incorporati. Il seguente codice ha come target i tipi di media all con orientamento verticale:

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

media="handheld"

Dobbiamo fermarci un attimo e discutere di media="handheld". Il fatto è che Android e iOS ignorano media="handheld". L'affermazione è che gli utenti perderanno i contenuti di fascia alta forniti dai fogli di stile che hanno come target media="screen" e che gli sviluppatori hanno meno probabilità di 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 l'ideale utilizzare questa funzionalità per scegliere come target i dispositivi mobili, ma vari browser l'hanno implementata in modi diversi:

  • Alcuni leggono solo il foglio di stile di sola lettura.
  • Alcuni leggono solo il foglio di stile per dispositivi portatili, se presente, ma per impostazione predefinita utilizzano il foglio di stile per lo schermo.
  • Alcuni leggono sia il foglio di stile per dispositivi portatili sia quello per lo schermo.
  • Alcuni leggono solo il foglio di stile dello schermo.

Opera Mini non ignora media="handheld". Il trucco per far sì che Windows Mobile riconosca media="handheld" è scrivere in maiuscolo il valore dell'attributo media per il foglio di stile dello schermo:

 <!-- 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 supporti

Le query supporti sono ampiamente utilizzate in html5rocks per dispositivi mobili. Ci hanno permesso di modificare il layout senza dover apportare modifiche significative al markup del nostro modello Django… un vero toccasana! Inoltre, il loro supporto nei vari browser è piuttosto buono.

Nella sezione <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 l'aspetto principale di html5rocks.com, ma ora stiamo applicando nuovi stili (mobile.css) per larghezze dello schermo inferiori a 800 px. La sua query supporti copre gli smartphone (~320 px) e l'iPad (~768 px). L'effetto: stiamo eseguendo l'override incrementale degli stili in base.css (solo se necessario) per migliorare l'aspetto sui dispositivi mobili.

Alcune delle modifiche di stile applicate da mobile.css:

  • Riduce gli spazi vuoti/il padding aggiuntivi nel sito. Gli schermi piccoli significano che lo spazio è prezioso.
  • Rimuove :hover stati. Non verranno mai visualizzati sui dispositivi touch.
  • Regola il layout in modo che sia a colonna singola. Ne parleremo meglio più avanti.
  • Rimuove l'elemento box-shadow intorno al div del contenitore principale del sito. Le ombreggiature dei riquadri di grandi dimensioni riducono le prestazioni della pagina.
  • Utilizzato il modello di layout CSS flexbox box-ordinal-group per modificare l'ordine di ogni sezione della home page. Noterai che la sezione "LEARN BY MAJOR HTML5 FEATURE GROUPS" precede la sezione "TUTORIALS" nella home page, ma la segue nella versione mobile. Questo ordine aveva più senso per i dispositivi mobili e non richiedeva modifiche al markup. Flexbox CSS FTW!
  • Rimuove opacity modifiche. La modifica dei valori alfa influisce sul rendimento sui dispositivi mobili.

Meta tag per dispositivi mobili

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 adattare i contenuti allo schermo del dispositivo e lo informa che il sito è ottimizzato per i dispositivi mobili. 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 una scala iniziale di 1. Questo esempio consente anche lo zoom, un'operazione che potrebbe essere utile 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 la risoluzione dello schermo per cui è 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 tua pagina web per diverse densità dello schermo, 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 tua pagina web e puoi apportare le modifiche necessarie per ogni densità tramite CSS e JavaScript.

Per saperne di più sul targeting delle risoluzioni dei dispositivi, consulta la documentazione di WebView di Android.

Navigazione a schermo intero

Esistono altri due valori meta specifici per iOS. apple-mobile-web-app-capable e apple-mobile-web-app-status-bar-style eseguiranno il rendering dei contenuti della pagina in modalità a schermo intero simile a un'app e renderanno la barra di stato traslucida:

 <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 un rel="apple-touch-icon" (iOS) e rel="apple-touch-icon-precomposed" (Android) per i link. Questi tag creano un'icona accattivante simile a quella di un'app nella schermata Home dell'utente quando aggiunge il tuo sito ai preferiti:

 <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

Sui dispositivi con schermi più piccoli, è molto più comodo scorrere in verticale che in orizzontale. Per i dispositivi mobili è preferibile mantenere i contenuti in un layout verticale a colonna singola. Per html5rocks, abbiamo utilizzato le query supporti CSS3 per creare un layout di questo tipo. Anche in questo caso, senza modificare il markup.

Indice dei tutorial. Tutorial. Pagina delle funzionalità HTML5. Pagina dei profili degli autori.
Layout verticale a colonna singola in tutto il sito.

Ottimizzazioni per il mobile

La maggior parte delle ottimizzazioni che abbiamo apportato sono cose che avrebbero dovuto essere fatte fin dall'inizio. Ad esempio, riducendo il numero di richieste di rete, comprimendo JS/CSS, utilizzando gzipping (disponibile senza costi su App Engine) e riducendo al minimo le manipolazioni del DOM. Queste tecniche sono best practice comuni, ma a volte vengono trascurate quando si ha fretta di pubblicare un sito.

Nascondi automaticamente la barra degli indirizzi

I browser mobile non hanno lo spazio sullo schermo della loro controparte desktop. A peggiorare le cose, su diverse piattaforme, a volte ti ritrovi con una grande barra degli indirizzi nella parte superiore dello schermo… anche dopo che la pagina è stata caricata.

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à nascosta. Per forzare la scomparsa della 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 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 listener nella nostra variabile di modello is_mobile, poiché non è necessario su computer.

Riduci le richieste di rete, risparmia larghezza di banda

È un fatto noto che la riduzione del numero di richieste HTTP può migliorare notevolmente le prestazioni. I dispositivi mobili limitano ulteriormente il numero di connessioni simultanee che il browser può effettuare, pertanto i siti mobile trarranno ancora più vantaggio dalla riduzione di queste richieste estranee. Inoltre, ridurre al minimo i byte è fondamentale perché la larghezza di banda è spesso limitata sugli smartphone. Potresti far spendere soldi agli 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) sulle 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, nascondevamo il markup se non si adattava al profilo mobile. Un buon esempio sono le quattro caselle arrotondate nella parte superiore della home page:

Pulsanti riquadro sulla home page.
Pulsanti dei riquadri nella home page.

Non sono presenti sul sito mobile. È importante ricordare che il browser effettua comunque una richiesta per ogni icona, anche se il relativo contenitore è nascosto con display:none. Pertanto, non era sufficiente nascondere questi pulsanti. Non solo si sprecherebbe larghezza di banda, ma l'utente non vedrebbe nemmeno i frutti di questa larghezza di banda sprecata. La soluzione è stata creare un valore booleano "is_mobile" nel nostro modello Django per omettere in modo condizionale sezioni di HTML. Quando l'utente visualizza il sito su uno smart device, i pulsanti vengono omessi.

  • Cache dell'applicazione: non solo ci offre il supporto offline, ma velocizza anche l'avvio.

  • Compressione CSS/JS: utilizziamo YUI Compressor anziché il compilatore Closure principalmente perché gestisce sia CSS che JS. Un problema che abbiamo riscontrato è che le query supporti incorporate (query supporti che vengono visualizzate all'interno di un foglio di stile) hanno causato un errore in YUI Compressor 2.4.2 (vedi questo problema). L'utilizzo di YUI Compressor 2.4.4 e versioni successive ha risolto il problema.

  • Utilizzo di sprite di immagini CSS, ove possibile.

  • Utilizzo di pngcrush per la compressione delle immagini.

  • Utilizza dataURI per le immagini di piccole dimensioni. La codifica base64 aggiunge circa il 30%di dimensioni all'immagine, ma evita la richiesta di rete.

  • La Ricerca personalizzata di Google è stata caricata automaticamente utilizzando un singolo tag di script anziché caricarla dinamicamente con google.load(). Quest'ultimo effettua una richiesta aggiuntiva.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • Il nostro formattatore di codice e Modernizr venivano inclusi in ogni pagina, anche se non venivano mai utilizzati. Modernizr è ottimo, 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 modifiche per il rendimento:

  • Spostato tutto il codice JS in fondo alla pagina (dove possibile).
  • Sono stati rimossi i tag <style> incorporati.
  • Ricerche DOM memorizzate nella cache e manipolazioni DOM ridotte al minimo: ogni volta che tocchi il DOM, il browser esegue un reflow. I reflow sono ancora più costosi su un dispositivo mobile.
  • Il codice lato client inefficiente è stato trasferito al server. In particolare, il controllo per 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 consentire agli utenti di leggere i contenuti offline.

Quando implementi AppCache sul tuo sito, è molto importante non memorizzare nella cache il file manifest (né esplicitamente nel file manifest stesso né 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 nella cache questo file in modo particolarmente efficace, ma non forniscono un modo pratico per svuotare la cache come fanno i browser desktop.

Per impedire la memorizzazione nella cache del nostro sito, abbiamo prima impostato App Engine in modo che non memorizzi 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 quando il download di un nuovo manifest è stato completato. 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 semplice il manifest. In altre parole, non richiamare ogni pagina del tuo sito. Basta elencare i file di immagini, CSS e JavaScript importanti. L'ultima cosa che vuoi fare è costringere il browser mobile a scaricare un numero elevato di asset a ogni aggiornamento della cache dell'app. Ricorda invece che il browser memorizzerà implicitamente nella cache una pagina HTML quando l'utente la visita (e include un attributo <html manifest="...">).