Cómo crear animaciones CSS de alto rendimiento

En esta guía, se explica cómo crear animaciones CSS de alto rendimiento.

Consulta ¿Por qué algunas animaciones son lentas? para conocer la teoría detrás de estas recomendaciones.

Compatibilidad del navegador

Todas las propiedades de CSS que se recomiendan en esta guía son compatibles con varios navegadores.

Cómo mover un elemento

Para mover un elemento, usa los valores de palabra clave translate o rotation de la propiedad transform.

Por ejemplo, para deslizar un elemento a la vista, usa translate.

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

Los elementos también se pueden rotar (en el ejemplo, a 360 grados).

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

Cambia el tamaño de un elemento

Para cambiar el tamaño de un elemento, usa el valor de palabra clave scale de la propiedad transform.

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

Cambia la visibilidad de un elemento

Para ocultar o mostrar un elemento, usa opacity.

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

Evita las propiedades que activen el diseño o la pintura

Antes de usar cualquier propiedad de CSS para la animación (que no sea transform ni opacity), determina el impacto de la propiedad en la canalización de renderización. Evita cualquier propiedad que active diseño o pintura, a menos que sea absolutamente necesario.

Forzar la creación de capas

Como se explica en ¿Por qué algunas animaciones son lentas?, cuando colocas los elementos en una capa nueva, se pueden volver a pintar sin tener que volver a pintar el resto del diseño.

Los navegadores suelen tomar buenas decisiones sobre qué elementos se deben colocar en una capa nueva, pero puedes forzar manualmente la creación de capas con la propiedad will-change. Como su nombre lo sugiere, esta propiedad indica al navegador que este elemento se modificará de alguna manera.

En CSS, esta propiedad se puede aplicar a cualquier selector:

body > .sidebar {
  will-change: transform;
}

Sin embargo, la especificación sugiere que solo se debe adoptar este enfoque para elementos que siempre están a punto de cambiar. Si el ejemplo anterior fuera una barra lateral, el usuario podría deslizarse hacia adentro y afuera, ese podría ser el caso. Es posible que algunos elementos de tu página no cambien con frecuencia, por lo que sería mejor aplicar will-change con JavaScript en un punto en el que sea probable que se produzca el cambio. Deberás asegurarte de darle tiempo al navegador suficiente para realizar las optimizaciones necesarias y, luego, quitar la propiedad una vez que se detenga el cambio.

Si necesitas una forma de forzar la creación de capas en uno de los navegadores poco comunes que no es compatible con will-change (lo más probable es que sea Internet Explorer en este punto), puedes configurar transform: translateZ(0).

Cómo depurar animaciones lentas o con bloqueos

Las Herramientas para desarrolladores de Chrome y las Herramientas para desarrolladores de Firefox tienen muchas herramientas que te ayudan a determinar por qué las animaciones son lentas o se bloquean.

Cómo comprobar si una animación activa un diseño

Es probable que una animación que mueve un elemento con otro elemento que no sea transform sea lenta. En el siguiente ejemplo, obtuve el mismo resultado visual con la animación de top y left, y usando transform.

Qué no debes hacer
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

Puedes probar esto en los siguientes dos ejemplos de Glitch y explorar el rendimiento con las Herramientas para desarrolladores.

Herramientas para desarrolladores de Chrome

  1. Abre el panel Rendimiento.
  2. Registra el rendimiento del tiempo de ejecución mientras se realiza la animación.
  3. Inspecciona la pestaña Summary.

Si ves un valor distinto de cero para Renderización en la pestaña Resumen, puede significar que la animación está haciendo que el navegador realice el trabajo de diseño.

En el panel Summary, se muestran 37 ms para la renderización y 79 ms para la pintura.
El ejemplo de animation-with-top-left genera un trabajo de renderización.
En el panel Summary, se muestran valores cero para la renderización y la pintura.
En el ejemplo de animación-con-transformación, no se produce ningún trabajo de renderización.

Herramientas para desarrolladores de Firefox

En las Herramientas para desarrolladores de Firefox, la cascada puede ayudarte a comprender en qué parte del navegador pasa tiempo.

  1. Abre el panel Rendimiento.
  2. En el panel, inicia la grabación del rendimiento mientras se reproduce la animación.
  3. Detén la grabación y, luego, inspecciona la pestaña Waterfall.

Si ves entradas para Volver a calcular el estilo, el navegador debe iniciarse al inicio de la cascada de renderización.

Cómo comprobar si una animación descarta fotogramas

  1. Abre la pestaña Rendering de las Herramientas para desarrolladores de Chrome.
  2. Habilita la casilla de verificación Medidor de FPS.
  3. Observa los valores mientras se ejecuta la animación.

En la parte superior de la IU del Medidor de FPS, verás la etiqueta Fotogramas. Debajo, verás un valor similar a las líneas de 50% 1 (938 m) dropped of 1878. Una animación de alto rendimiento tendrá un porcentaje alto, p.ej., 99%. Un porcentaje alto significa que se descartan pocos fotogramas y que la animación se verá fluida.

El medidor de FPS muestra que el 50% de los fotogramas se omitieron
El ejemplo de animation-with-top-left hace que se pierda un 50% de los fotogramas
El medidor de FPS muestra que solo se omitió el 1% de los fotogramas
El ejemplo animación-con-transformación causa solo un 1% de los fotogramas.

Cómo comprobar si una animación activa la pintura

Cuando se trata de pintar, algunas cosas son más costosas que otras. Por ejemplo, todo lo que incluya un desenfoque (como una sombra, por ejemplo) tardará más en pintar que dibujar un cuadro rojo. Sin embargo, en términos de CSS, esto no siempre es obvio: background: red; y box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); no necesariamente parecen tener características de rendimiento muy diferentes, pero sí.

Las Herramientas para desarrolladores del navegador pueden ayudarte a identificar qué áreas debes volver a pintar y problemas de rendimiento relacionados con la pintura.

Herramientas para desarrolladores de Chrome

  1. Abre la pestaña Rendering de las Herramientas para desarrolladores de Chrome.
  2. Selecciona Paint Flashing.
  3. Mueve el puntero por la pantalla.
Un elemento de la IU destacado en verde para demostrar que se volverá a pintar
En este ejemplo de Google Maps, puedes ver los elementos que se volverán a pintar.

Si ves toda la pantalla parpadeante o las áreas que crees que no deberían cambiar destacadas, puedes hacer una investigación.

Si necesitas analizar si una propiedad en particular está causando problemas de rendimiento debido a la pintura, el generador de perfiles de pintura de las Herramientas para desarrolladores de Chrome puede ayudarte.

Herramientas para desarrolladores de Firefox

  1. Abre Configuración y agrega un botón de Caja de herramientas para Toggle paint flashing.
  2. En la página que deseas inspeccionar, activa el botón y mueve el mouse o desplázate para ver las áreas destacadas.

Conclusión

Cuando sea posible, restringe las animaciones a opacity y transform para mantener las animaciones en la etapa de composición de la ruta de renderización. Utiliza las Herramientas para desarrolladores para verificar qué etapa de la ruta de acceso se ve afectada por tus animaciones.

Usa el generador de perfiles de pintura para ver si alguna operación de pintura es particularmente costosa. Si encuentras algo, comprueba si otra propiedad de CSS tendrá el mismo aspecto y un mejor rendimiento.

Usa la propiedad will-change con moderación y solo si encuentras un problema de rendimiento.