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