Cargando imágenes de una forma óptima

 

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Qué hago

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Page Load Time

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Versión A

React

Alicante

2017

Speakers & Schedule

0.0s

0.3s

0.6s

0.9s

1.2s

Versión B

React

Alicante

2017

Speakers & Schedule

0.0s

0.3s

0.6s

0.9s

1.2s

React

Alicante

2017

Speakers & Schedule

React

Alicante

2017

React

Alicante

2017

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Rendimiento percibido por el usuario

(User Perceived Performance)

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Speed Index = \int_0^{fin} 1 - \frac{R}{100}
SpeedIndex=0fin1R100Speed Index = \int_0^{fin} 1 - \frac{R}{100}

fin = tiempo final en milisegundos

R = % de pantalla renderizado

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

WebPageTest

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Más kilobytes

 

mejorar el rendimiento percibido

puede, a veces,

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Evitando esto:

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Técnicas para mejorar el rendimiento percibido

  • Server-side rendering
  • Critical CSS
  • JS Async
  • Fuentes Async

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

¿Qué pasa con las imágenes?

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

imágenes

1795kB (54%)

scripts

453kB (14%)

vídeos

756kB (23%)

fuente: http archive 15 agosto 2017

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Usar o no usar imágenes

Reduce las peticiones de imágenes

CONSEJO 1

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

en especial las de mapa de bits (JPG, PNG, WebP...)

Minimalismo | Diseño Flat

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Hace no mucho tiempo...

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

<img src="example.png"> <!-- el navegador hará la petición -->
@media (max-width: 480px) {
    img {
        display: none;
    }
}

Cómo NO ocultar imágenes (1/2)

HTML

CSS

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

<body>
    <section class="section-1">
        <p>Esta es la sección actual</p>
	<img src="example-1.png">
    </section>
    <section class="section-2 hidden">
	<p>Esta sección quizás se muestre luego</p>
	<img src="example-2.png"> <!-- el navegador pedirá esta imagen -->
    </section>
</body>
.hidden { display: none; }

Cómo NO ocultar imágenes (2/2)

HTML

CSS

Optimiza tus imágenes

CONSEJO 2

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

formato adecuado

gif | png | jpg | webp | <lo_que_venga_después>

<picture>
    <source type="image/webp" srcset="2700x1209/mi-imagen.webp 2700w, 
                    1024x1024/mi-imagen.webp 1024w, 
                    600x600/mi-imagen.webp 600w" 
            sizes="100vw" />
    <source srcset="2700x1209/mi-imagen.jpg 2700w, 
                    1024x1024/mi-imagen.jpg 1024w, 
                    600x600/mi-imagen.jpg 600w" 
            sizes="100vw" />
    <img src="600x600/mi-imagen.jpg" alt="Mi preciosa imagen" />
</picture>

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

compresión

· sin pérdida (lossless)

· perceptual

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

1 columna

2 columnas

3 columnas

Responsive

CONSEJO 3

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

<img sizes="(max-width: 30em) 100vw,
            (max-width: 50em) 50vw,
            calc(33vw - 100px)"
     srcset="profile-200.jpg 200w,
             profile-400.jpg 400w,
             profile-800.jpg 800w,
             profile-1600.jpg 1600w"
     src="profile-400.jpg" alt="Alicante">

Reto: Mantener sincronizado el markup y el CSS

Ejemplo

IMÁGENES RESPONSIVE

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Usar lazy-loading en imágenes

CONSEJO 4

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

<img> encima del fold

&

Lazy debajo del fold

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Intersection

Observer

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

// cargar imagen cuando esté a <= 100 px del viewport

const options = {
  rootMargin: '100px'
}

const callback = entries => { 
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
        // cargar imagen
    }
  });
};

const observer = new IntersectionObserver(callback, options);
observer.observe(document.querySelector('.lazy-img'));

Ejemplo

INTERSECTION OBSERVER

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

class LazyImage extends React.Component {

    constructor() {
        this.observer = new IntersectionObserver(entries => {
            if (entries[0].intersectionRatio > 0) {
                // ¡hacer la petición!
            }
        });
        this.element = null;  /* render() le dará valor a través de un ref */
    }

    componentDidMount() {
        this.observer.observe(this.element);
    }

    componentWillUnmount() {
        this.observer.unobserve(this.element);
    }
    ...
}

Encapsulación en React

INTERSECTION OBSERVER

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Soporte

INTERSECTION OBSERVER

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Qué mostrar mientras la imagen se está cargando

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Opciones

PLACEHOLDERS

Nada

Placeholder

Color sólido

Carga progresiva o "Blur-up"

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Ejemplos de colores sólidos

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Ejemplos de

carga progresiva de imágenes

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Medium

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Medium

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Quartz (qz.com)

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Quartz (qz.com)

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Quora

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Cómo se hace

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

HTML - Medium

<figure>
  <div>

    <div/> <!-- este div mantiene el espacio con la correcta
                proporción de la imagen, para que no se "colapse" -->

    <img/> <!-- pequeña imagen con baja resolución (por
                ejemplo 27x17) y baja calidad -->

    <canvas/> <!-- toma la imagen anterior y aplica filtro "blur" -->

    <img/> <!-- la imagen final (grande) que se va a mostrar -->

    <noscript/> <!-- fallback para cuando no hay JS -->

  </div>
</figure>

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

JPEGs progresivos

Baseline

Progressive

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Con el método de JPEGs progresivos [...] la fluidez cognitiva se inhibe y el cerebro tiene que hacer un mayor esfuerzo para darle sentido a lo que se está mostrando.

— De Progressive image rendering: Good or evil?

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Thumbnails

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

42 x 42px con máxima compresión

Fuente: https://jmperezperez.com/webp-placeholder-images/

Siendo creativos con SVGs

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

SVG

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

SVG

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Dibujando con SVG

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Dibujando imágenes

de mapa de bits

Canny Edge Detector

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

<svg>
  <polyline points="51,1 61,1 61,2 56,4 56,3"/>
  <polyline points="52,1 50,2 51,3 50,4 50,9 46,10 46,8 48,8 48,9"/>
  <polyline points="61,4 61,5 58,6"/>
  ...
  <polyline points="62,58 61,59 61,60 50,62 50,61 51,61"/>
</svg>
  1. Buscar el contorno con un detector de bordes Canny
  2. Crear líneas
  3. Usar JS y SVG para animar

Cómo dibujar imágenes

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

¿Deberíamos hacer esto?

Que se pueda hacer no significa que se deba hacer

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

  • Reducir peticiones
  • Elegir el formato adecuado y optimizar
  • Utilizar imágenes responsive
  • Aplicar lazy loading
  • ¡Innovar!

Resumen

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

Desarrollar Web es divertido.

CARGANDO IMÁGENES EN LA WEB

@jmperezperez

buscamos desarrolladores web,

preguntadme para saber más

¡Gracias!

@jmperezperez

Cargando imágenes en la web de una forma óptima

By José M. Pérez

Cargando imágenes en la web de una forma óptima

Esta charla trata sobre la carga de imágenes en la web. Nos gusta hablar de JS y CSS y cómo optimizarlos, pero tendemos a olvidarnos de las imágenes, que representan más del 50% de los bytes de una página. La petición más eficaz es la que nunca se realiza, y esto supera cualquier optimización de imagen posible. Existen algunos escenarios comunes en los que podemos evitar el uso de imágenes, adoptando un diseño minimalista / flat u ocultando ciertas imágenes en pantallas más pequeñas. Por supuesto, tendremos que usar algunas imágenes en su debido momento. Para estos casos explico cómo el elemento puede ayudar y algunas de sus limitaciones que he encontrado al trabajar con sitios web reales. Uno de ellos es la carga lazy de imágenes, lo que puede aportar grandes ahorros en términos de tráfico de datos, pero también es fácil de implementar erróneamente. Por último, muestro algunas técnicas para "llenar" el espacio de una imagen mientras se carga, pasando de mostrar un área vacía a hacer una carga progresiva desde una imagen borrosa.

  • 4,096