Evitar las pinturas es fundamental para lograr una velocidad de fotogramas fluida, especialmente en dispositivos móviles. Sin embargo, a veces, las pinturas aparecen en los lugares más inusuales. En este artículo, se analiza por qué los GIFs animados pueden causar que se produzcan pinturas innecesarias y la solución muy sencilla que puedes aplicar.
Capas de belleza
Como probablemente sepas, los navegadores modernos pueden pintar grupos de elementos del DOM en "imágenes" separadas, llamadas capas. A veces, hay una capa para toda la página, a veces hay cientos o, en casos excepcionales, ¡miles!
Cuando los elementos del DOM se agrupan en una capa y uno de ellos cambia visualmente, terminamos teniendo que pintar no solo el elemento modificado, sino todos los demás elementos de la capa que se superponen con el elemento modificado. Si pintas un elemento sobre otro, los píxeles reemplazados se “pierden” para siempre. Si quieres recuperar los píxeles originales, debes volver a pintarlos.
Por lo tanto, a veces, queremos aislar un elemento de los demás para que, cuando se pinte, no tengamos que volver a pintar los otros elementos que no cambiaron. Por ejemplo, cuando combinas un encabezado de página fijo con contenido desplazable, debes volver a pintar el encabezado cada vez que se desplaza el contenido, así como el contenido que se vuelve visible. Si colocas el encabezado en una capa independiente, el navegador puede optimizar el desplazamiento. Cuando te desplazas, el navegador puede mover las capas, probablemente con la ayuda de la GPU, y evitar volver a pintar ninguna.
Cada capa adicional aumenta el consumo de memoria y agrega sobrecarga de rendimiento, por lo que el objetivo es agrupar la página en la menor cantidad posible de capas y, al mismo tiempo, mantener un buen rendimiento.
¿Qué tiene todo esto que ver con los GIFs animados?
Veamos esta imagen:

Esta es una posible configuración de capas para una app simple. Hay cuatro capas: tres de ellas (de la 2 a la 4) son elementos de interfaz; la capa posterior es un cargador, que es un GIF animado. En el flujo normal, se muestra el cargador (capa 1) mientras se carga la app y, luego, cuando todo termina, se muestran las otras capas. Pero aquí está la clave: debes ocultar el GIF animado.
Pero ¿por qué debo ocultarlo?
Buena pregunta. En un mundo ideal, el navegador simplemente verificaría la visibilidad del GIF y evitaría pintar automáticamente. Lamentablemente, verificar si el GIF animado está oculto o es visible en la pantalla suele ser más costoso que simplemente pintarlo, por lo que se pinta.
En el mejor de los casos, el GIF está en su propia capa y el navegador solo tiene que pintarlo y subirlo a la GPU. Sin embargo, en el peor de los casos, es posible que todos tus elementos se agrupen en una sola capa y el navegador tenga que volver a pintar cada elemento. Y, cuando termine, aún deberá subir todo a la GPU. Todo este trabajo se realiza para cada fotograma del GIF, a pesar de que el usuario ni siquiera puede ver el GIF.
En computadoras de escritorio, es probable que puedas usar este tipo de comportamiento de pintura porque las CPUs y las GPUs son más potentes y hay mucho ancho de banda para transferir datos entre ambas. Sin embargo, en dispositivos móviles, la pintura es extremadamente costosa, por lo que debes tener mucho cuidado.
¿A qué navegadores afecta esto?
Como suele suceder, los comportamientos difieren entre navegadores. Actualmente, Chrome, Safari y Opera vuelven a pintar el GIF, incluso si está oculto. Firefox, por otro lado, determina que el GIF está oculto y no es necesario volver a pintarlo. Internet Explorer sigue siendo una caja negra, y, incluso en IE11, dado que las herramientas de F12 aún se están desarrollando, no hay indicios de si se está realizando algún proceso de repintado.
¿Cómo puedo saber si tengo este problema?
La forma más fácil es usar "Show paint rectangles" en las Herramientas para desarrolladores de Chrome. Carga DevTools, presiona el engranaje en la esquina inferior derecha () y elige Show paint rectangles en la sección Rendering.

Ahora, solo debes buscar un rectángulo rojo como este:

El pequeño cuadro rojo en la pantalla muestra que Chrome está volviendo a pintar algo. Sabes que hay un GIF de cargador oculto detrás de los otros elementos, por lo que, cuando veas un cuadro rojo como este, debes ocultar los elementos visibles y verificar si dejaste el GIF animado girando. Si es así, debes agregar CSS o JavaScript para aplicar display: none
o visibility: hidden
a él o a su elemento superior. Por supuesto, si solo es una imagen de fondo, asegúrate de quitarla.
Si quieres ver un ejemplo de este comportamiento en un sitio en vivo, consulta Allegro, en el que la imagen de cada producto tiene un GIF de cargador que está oculto en lugar de estar oculto de forma explícita.
Conclusión
Lograr 60 fps significa hacer solo lo necesario para renderizar la página y nada más. Quitar el exceso de pintura es un paso fundamental para lograr este objetivo. Los GIFs animados que se dejan en ejecución pueden activar pinturas innecesarias, algo que puedes encontrar y depurar fácilmente con la herramienta Mostrar áreas procesadas con rectángulos destacados de DevTools.
No dejaste ese GIF animado del cargador de gatitos ejecutándose para siempre, ¿verdad?