Every second counts

Fonte: Kissmetrics Blog

La velocità di caricamento rappresenta un aspetto fondamentale di cui tenere conto nella costruzione di un sito web moderno per evitare che gli utenti abbandonino prematuramente la navigazione. La rete sta infatti vivendo in questi anni un overload di contenuti: ogni risorsa è disponibile in versioni simili, se non del tutto identiche, su svariati siti e l’utente non è più costretto a visitare forzatamente un unico sito per reperirla ma qualora l’esperienza di navigazione non sia soddisfacente può rivolgersi altrove… e certamente lo farà.

Per dare qualche numero, fonti statistiche dicono che il tasso di abbandono raggiunge il 25% quando il tempo di risposta di un sito supera i 4 secondi e sale addirittura al 50% quando ci si avvicina ai 10 secondi di attesa.

Common problen when accessing a website from a mobile phone

Fonte: Kissmetrics Blog

Non dobbiamo poi dimenticare gli utenti mobile, che sono sempre in aumento e che spesso si connettono al nostro sito da linee più lente di quelle presenti nelle abitazioni e soprattutto lo visualizzano su schermi più piccoli; è necessario fornire loro contenuti ottimizzati, che si scarichino velocemente e si visualizzino bene anche su dispositivi piccoli. Sempre per fornire qualche statistica, il 73% degli utenti mobile lamenta di aver sperimentato qualche volta siti troppo lenti ed il 51% ha incontrato siti che nella loro versione mobile vanno in crash o in freeze.

C’è velocità e velocità…

Ma quale velocità devo considerare nella mia attività di costruzione ed ottimizzazione del sito? Certamente il primo pensiero sarà il tempo totale di caricamento della pagina, cioè il tempo che intercorre tra la ricezione dei primi dati da parte del browser dell’utente e la visualizzazione completa della pagina web nella finestra dello stesso. In realtà questo dato, seppur importante, non è fondamentale

Molto più importante dal punto di vista della user experience è invece il tempo di primo render della pagina, cioè il tempo che passa tra la richiesta della pagina e la visualizzazione a schermo del numero minimo di elementi per permetterne una prima navigazione. Se la nostra pagina rimane bianca troppo a lungo certamente l’utente l’abbandonerà, sospettando magari un malfunzionamento ma se riusciamo a mostrare in un tempo ragionevolmente breve un numero di elementi testuali e grafici sufficiente per dare all’utente l’impressione che la pagina stia caricando correttamente e permettergli già una navigazione di massima il tempo totale di caricamento passerà in secondo piano.

Uno strumento estremamente potente per eseguire un’analisi delle proprie pagine è Web Page Test: esegue tre test successivi di caricamento della pagina, tenendo quindi conto anche del caching lato client degli elementi e fornisce in formato grafico e tabellare tutti i tempi di caricamento. Oltre al tempo totale di caricamento (Load time) vengono indicati il tempo di attesa prima di ricevere il primo byte di dati (First byte) e quello di rendering della pagina, oltre ad un utilissimo indice denominato Speed Index, calcolato secondo un algoritmo proprietario tenendo conto della velocità con cui la prima schermata della pagina viene popolata di elementi visuali.

Ok, tutto bellissimo ma come faccio a velocizzare il mio sito?
Vediamo di seguito alcuni punti su cui intervenire, sia direttamente nel codice delle nostre pagine che lato server.

Ottimizzare le immagini

Le immagini sono ormai presenti in ogni punto di una pagina web, dalla più piccola icona alla fotografia e per via del loro peso spesso significativo costituiscono la principale fonte di rallentamento nel caricamento della pagina.

La prima regola, forse scontata ma mai banale, è quella di ottimizzare le immagini, riducendone il più possibile il peso in byte preservandone qualità e dettagli. Inoltre sarebbe buona norma utilizzare immagini JPEG progressive: queste immagini vengono visualizzate dal browser man mano che vengono scaricate, senza attendere il download completo. Esistono delle utility, come ad esempio JPEGTran per creare delle copie delle proprie immagini JPEG ottimizzate e progressive da utilizzare online. PNGOUT è invece un tool analogo per ottimizzare le immagini PNG.

Se poi la nostra pagina è più lunga di una schermata perché caricare tutte le immagini presenti e non aspettare invece che l’utente scorra verso il basso caricandole al volo solo quando è necessario? Questa tecnica, denominata lazy load, può essere implementata facilmente utilizzando dei piccoli script come ad esempio Vanilla LazyLoad.

Una sola immagine, tante dimensioni

Certamente le immagini presenti nella nostra pagina dovranno essere visualizzate diversamente su uno smartphone piuttosto che su un computer desktop e dovranno essere adeguate alle varie risoluzioni degli schermi. Predisporre una sola immagine alla massima risoluzione necessaria ed utilizzarla a tutte le risoluzioni, demandando al browser il compito di riscalarla adeguatamente, pur se possibile ha due grandi svantaggi:
1. L’utente sarà costretto a scaricare inutilmente un’immagine molto pesante, con allungamento dei tempi di caricamento e spreco di dati se si è su una connessione mobile;
2. I browser non implementano algoritmi di ridimensionamento particolarmente brillanti… per cui la nostra immagine certamente perderà di qualità.

La soluzione è preparare a priori diverse versioni della nostra immagine, con diverse risoluzioni (vedremo tra poco quali) e volendo anche diversi tagli ed indicarle tutte quante al browser; sarà poi lui che, conoscendo lo schermo su cui sta operando, deciderà quale versione dell’immagine mostrare. Per far questo la strada migliore è avvalersi degli attributi srcset e sizes del classico tag <img>: questi attributi sono stati introdotti con la specifica HTML 5.1, passata allo stato di recommandation nel novembre del 2016 e già ampiamente supportata da tutti i principali browser come si può vedere nella tabella sotto. Rimane escluso Internet Explorer, utilizzato su Windows sino alla versione 8.1 (Windows 10 introduce Edge) ma questo non è un problema, semplicemente IE non interpreterà i nuovi attributi e continuerà a mostrare l’immagine di base.

Srcset and sizes attributes

Fonte: caniuse.com

Vediamo alcuni esempi pratici, partendo dalla necessità di supportare i display cosiddetti retina utilizzati nei più recenti smartphone e tablet. Questi schermi hanno una densità di pixel talmente alta da fare in modo che l’occhio umano non sia in grado di distinguere i singoli pixel ma per fare questo richiedono che le immagini vengano fornite ad una risoluzione doppia di quella originale. Prepariamo quindi due immagini, una base (immagine_1x.jpg) ed una grande esattamente il doppio (immagine_2x.jpg) e forniamole al browser in questo modo:

<img src="immagine_1x.jpg"
     srcset="immagine_1x.jpg 1x, 
             immagine_2x.jpg 2x"
     alt="descrizione immagine"
     width="1280"
     height="720" />

Gli identificatori 1x e 2x all’interno del parametro srcset identificano rispettivamente l’immagine originale e quella a grandezza doppia.

Come fare invece per fornire l’immagine più adatta ad ogni risoluzione dello schermo? Facilissimo:

<img src="immagine_1280.jpg" 
     srcset="immagine_1280.jpg 1280w,
             immagine_1024.jpg 1024w,
             immagine_768.jpg   768w"
     alt="descrizione immagine"
     sizes="100vw" />

Abbiamo preparato tre diverse immagini, tutte con la stessa proporzione ma larghe rispettivamente 1280, 1024 e 768 pixel e le abbiamo inserite nell’attributo srcset, indicando per ciascuna al browser la sua larghezza con il modificatore w, come ad esempio 1280w. Al posto dell’indicazione esplicita della larghezza ed altezza che dovrà assumere l’immagine vi è il nuovo attributo sizes con valore 100vw che significa “100% della viewport width”, cioè 100% della larghezza dello schermo; naturalmente si poteva inserire qualunque valore al posto di 100. Con queste indicazioni, il browser è in grado autonomanente di scegliere e scaricare la versione più adatta dell’immagine.

Non è detto che a tutte le risoluzioni l’immagine debba avere la stessa dimensione relativamente al viewport… ad esempio su un PC desktop potrebbe essere larga soltanto il 50% in un layout a due colonne e su tablet passare a tutta larghezza. Per questo l’attributo sizes accetta una serie illimitata di valori separati da virgole:

<img src="immagine_1280.jpg"
     srcset="immagine_1280.jpg 1280w,
             immagine_1024.jpg 1024w,
             immagine_768.jpg   768w"
     alt="descrizione immagine"
     sizes="(min-width: 1024px) 50vw, 100vw" />

Attenzione soltanto all’ordine in cui i valori vengono dichiarati, perché verranno esaminati partendo dall’alto e l’esame si arresterà appena viene trovato il primo valore compatibile con lo schermo in uso.

Possiamo fare ancora un passo ulteriore: se alle diverse risoluzioni volessimo utilizzare immagini non solo con dimensioni diverse ma anche con diverse proporzioni? Un caso tipico è l’immagine di testata di un sito che potrebbe ad esempio essere orizzontale su tablet e verticale su smartphone. In questo caso dobbiamo utilizzare il tag <picture>, il cui supporto da parte dei vari browser è lo stesso visto per i precedenti attributi. Pur non nativamente supportato, è possibile utilizzarlo anche su Internet Explorer ricorrendo a degli script che ne simulano il comportamento, ad esempio PictureFill.

<picture>
   <source media="(min-width: 768px)"
           srcset="immagine_1024_l.jpg 1x, 
                   immagine_2048_l.jpg 2x">
   <img src="immagine_512_p.jpg" 
        srcset="immagine_512_p.jpg  1x, 
                immagine_1024_p.jpg 2x" 
        alt="descrizione immagine">
</picture>

Nel tag <source> abbiamo indicato che a partire da una larghezza minima dello schermo di 768 pixel,  dovrà essere utilizzata l’immagine immagine_1024_l.jpg con la sua corrispondente a 2x per i display retina; in caso di schermi più piccoli questa regola non sarà rispettata e si scenderà quindi ad utilizzare il classico tag <img> che caricherà l’immagine verticale immagine_512_p.jpg. Prima del tag <img> è possibile inserire tutti i tag <source> desiderati, ciascuno con il suo attributo media che ne discriminerà la scelta.

Ma quante versioni della mia immagine dovrei preparare per supportare tutti i dispositivi su cui verrà visto il mio sito? In linea generale si dovrebbe prendere in considerazione la larghezza degli schermi più utilizzati, calcolare la dimensione che avrà la nostra immagine su tutti questi schermi a partire dallo spazio che occuperà su di essi e ritagliare poi il minor numero possibile di immagini, eventualmente riutilizzando qualche taglio a diverse risoluzioni.

Device & Orientamento Larghezza contenitore Screen density Pixel fisici
iPhone 4/5/5s 320 2 640
iPhone 6 375 2 750
iPhone 5/5s landscape 568 2 1136
iPhone 6 landscape 667 2 1334
iPad 768 2 1536
iPad landscape 1024 2 2048
PC 1280 1 1280
PC HiDPI 1280 2 2560

Esistono anche dei potenti strumenti online, come ad esempio Responsive Breakpoint Generator che fornisce automaticamente tutte le immagini responsive ritagliate a partire dall’immagine originale con tante opzioni configurabili, come le risoluzioni minima e massima dello schermo, il numero massimo di immagini da realizzare sino alla variazione di peso tra un’immagine e la successiva.

Fino ad ora abbiamo parlato di immagini caricate direttamente dal codice HTML della pagina ma se volessimo adeguare agli schermi ad alta densità anche immagini utilizzate come sfondi di elementi?
In questo caso possiamo sfruttare una semplice regola CSS:

.sfondo {
   background-image: url(immagine_1x.jpg);
   @media
   only screen and (-webkit-min-device-pixel-ratio: 2),
   only screen and (        min-device-pixel-ratio: 2),
   only screen and (                min-resolution: 192dpi),
   only screen and (                min-resolution: 2dppx) {
      background-image: url(immagine_2x.jpg);
      background-size: 1280px 500px;
   }
}

Il formato WebP

WebPNel settembre del 2010 Google ha reso pubblico un nuovo formato aperto di compressione per le immagini, dedicato espressamente all’utilizzo su web e denominato WebP. Attualmente è supportato nativamente solamente dai browser Chrome ed Opera ma il suo utilizzo si sta diffondendo sempre di più, ad esempio Facebook supporta ufficialmente il formato già dal 2013.

WebP supporta la trasparenza come il PNG e le animazioni analogamente alle immagini GIF, inoltre è possibile scegliere se realizzare immagini lossless, senza perdita di qualità come le PNG oppure lossy, con compressione maggiore a scapito della qualità.

Il grande interesse per questo formato nasce dalla forte capacità di compressione senza significative perdite di qualità: si parla del 26% di peso in meno rispetto ad una PNG lossless di pari dimensione ed addirittura, in formato lossy, di una riduzione dal 25% al 34% rispetto al corrispondente JPEG.