Por que algumas animações estão lentas?

Os navegadores mais recentes podem animar duas propriedades CSS de maneira econômica: transform e opacity. Se quiser fazer mais alguma animação, você provavelmente não vai alcançar a marca de 60 quadros por segundo (QPS). Este artigo explica por que isso acontece.

Desempenho da animação e frame rate

É amplamente aceito que uma taxa de quadros de 60 QPS é o objetivo para qualquer animação na Web. Esse frame rate garante que as animações fiquem suaves. Na Web, um frame é o tempo necessário para fazer todo o trabalho necessário para atualizar e repintar a tela. Se cada frame não for concluído em até 16,7 ms (1.000 ms / 60 ÷ 16,7), os usuários vão perceber o atraso.

O pipeline de renderização

Para exibir algo em uma página da Web, o navegador precisa passar pelas seguintes etapas:

  1. Estilo: calcule os estilos que se aplicam aos elementos.
  2. Layout: gere a geometria e a posição de cada elemento.
  3. Paint: preencha os pixels de cada elemento em camadas.
  4. Composto: desenhe as camadas na tela.

Essas quatro etapas são conhecidas como o pipeline de renderização do navegador.

Quando você anima algo em uma página que já foi carregada, essas etapas precisam acontecer de novo. Esse processo começa na etapa que precisa ser alterada para permitir que a animação ocorra.

Como mencionado antes, essas etapas são sequenciais. Por exemplo, se você animar algo que muda o layout, as etapas de pintura e composição também precisam ser executadas novamente. Animar algo que muda o layout é mais caro do que animar algo que só muda a composição.

Como animar propriedades de layout

As mudanças de layout envolvem o cálculo da geometria (posição e tamanho) de todos os elementos afetados pela alteração. Se você alterar um elemento, a geometria dos outros elementos poderá precisar ser recalculada. Por exemplo, se você mudar a largura do elemento <html>, qualquer um dos filhos dele poderá ser afetado. Devido à maneira como os elementos transbordam e afetam uns aos outros, mudanças mais abaixo na árvore podem resultar em cálculos de layout até o topo.

Quanto maior a árvore de elementos visíveis, mais tempo levará para realizar cálculos de layout.

Como animar propriedades de pintura

A pintura é o processo de determinar em qual ordem os elementos precisam ser pintados na tela. Muitas vezes, é a tarefa mais longa do pipeline.

A maior parte da pintura em navegadores modernos é feita em varreizadores de software. Dependendo de como os elementos do app são agrupados em camadas, outros elementos além daquele que mudou também precisam ser pintados.

Como animar propriedades compostas

A composição é o processo de dividir a página em camadas, converter as informações sobre a aparência da página em pixels (rasterização) e reunir as camadas para criar uma página (composição).

É por isso que a propriedade opacity está incluída na lista de recursos de animação baratos. Desde que essa propriedade esteja na própria camada, as mudanças podem ser processadas pela GPU durante a etapa de composição. Os navegadores baseados no Chromium e o WebKit criam uma nova camada para qualquer elemento que tenha uma transição ou animação CSS em opacity.

O que é uma camada?

Ao colocar os itens que serão animados ou transferidos em uma nova camada, o navegador só precisa repintar esses itens e não todo o restante. Você pode estar familiarizado com o conceito de uma camada do Photoshop que contém vários elementos que podem ser movidos juntos. As camadas de renderização do navegador são semelhantes a essa ideia.

Embora o navegador faça um bom trabalho ao tomar decisões sobre quais elementos precisam estar em uma nova camada, se ele perder algum, há maneiras de forçar a criação de camadas. Saiba mais sobre isso em Como criar animações de alto desempenho. No entanto, a criação de novas camadas precisa ser feita com cuidado, porque cada uma delas usa memória. Em dispositivos com memória limitada, a criação de novas camadas pode causar mais problemas de desempenho do que o que você está tentando resolver. Além disso, é preciso fazer upload das texturas de cada camada na GPU. Portanto, é possível atingir as restrições de largura de banda entre a CPU e a GPU.

Performance de CSS em comparação com JavaScript

Você pode se perguntar: é melhor, do ponto de vista do desempenho, usar CSS ou JavaScript para animações?

Animações baseadas em CSS e animações da Web (nos navegadores compatíveis com a API) costumam ser processadas em uma linha de execução conhecida como linha de execução do compositor. Isso é diferente da linha de execução principal do navegador, em que estilo, layout, pintura e JavaScript são executados. Isso significa que, se o navegador estiver executando algumas tarefas caras na linha de execução principal, essas animações podem continuar sem serem interrompidas.

Conforme explicado neste artigo, outras mudanças em transformações e opacidade podem, em muitos casos, também ser processadas pela linha de execução do compositor.

Se qualquer animação acionar uma pintura, um layout ou ambos, a linha de execução principal será necessária para realizar o trabalho. Isso é verdadeiro para animações CSS e JavaScript, e a sobrecarga de layout ou pintura provavelmente deixará menos trabalho associado à execução de CSS ou JavaScript, tornando a questão questionável.