Animação ruim chama atenção para o mecanismo. O card engasga, o menu deixa um rastro e a hero disputa CPU com o formulário. Em páginas criadas por IA, esse problema aparece quando cada pedido acrescenta mais um fade, parallax ou efeito infinito sem medir o conjunto.

Desligar tudo pode esconder a causa e remover feedback útil. Trocar top por transform também não encerra o diagnóstico. A página pode continuar pintando áreas enormes, promovendo camadas demais ou executando JavaScript em cada frame.

Grave o efeito na URL real, descubra qual etapa do pipeline custa caro e faça uma mudança por vez.

Comece pela animação que interfere na tarefa

Priorize movimento que acontece enquanto a pessoa tenta usar a página:

  • menu abrindo;
  • accordion expandindo;
  • card reagindo ao toque;
  • formulário mostrando validação;
  • modal entrando e saindo;
  • carrossel trocando slides;
  • elemento acompanhando scroll;
  • hero animada durante a primeira interação.

Uma ilustração discreta no rodapé pode consumir recursos, mas o menu que trava merece atenção primeiro.

Registre:

URL e Version:
dispositivo e CPU:
ação que inicia a animação:
duração declarada:
propriedades animadas:
frames lentos observados:
trabalho em JavaScript, Style, Layout, Paint e Composite:
preferência de movimento reduzido testada:

Leia o pipeline de um frame

Uma mudança visual pode passar por etapas diferentes:

  1. JavaScript atualiza estado ou estilo;
  2. o navegador recalcula estilos;
  3. calcula layout quando tamanho ou posição geométrica mudam;
  4. pinta pixels quando a aparência muda;
  5. compõe as camadas na tela.

O guia de rendering performance mostra os caminhos possíveis. Uma mudança que chega direto à composição evita layout e paint naquele frame. Isso costuma ser desejável em animações frequentes.

Propriedades como width, height, top e left podem exigir layout. Cores, sombras e filtros podem exigir paint ou ter custos próprios. transform e opacity são as opções mais previsíveis para limitar o trabalho à composição, quando o navegador consegue promovê-las corretamente.

Não memorize uma lista e encerre a revisão. Use o DevTools para confirmar o caminho real.

Grave no painel Performance

Abra o painel Performance, configure a CPU e grave a ação completa. Repita o efeito algumas vezes dentro da mesma captura.

Observe:

  • trilha Frames e quedas de taxa;
  • tarefas longas na thread principal;
  • eventos de Recalculate Style, Layout e Paint;
  • trilha Animations;
  • triângulos vermelhos em animações que não ficaram na composição;
  • área pintada e atividade de rasterização;
  • função que iniciou cada frame quando há JavaScript.

A referência atual do painel Performance mostra que animações sem composição aparecem com alerta e explica como abrir os motivos no resumo.

O painel Animations serve para desacelerar, pausar e inspecionar CSS animations, transitions, Web Animations e View Transitions. A documentação do painel Animations alerta que ele não captura animações implementadas com requestAnimationFrame. Para essas, use o trace de Performance.

Use as ferramentas de Rendering para enxergar o custo

Abra o painel Rendering pelo menu de comandos e ative uma ferramenta por vez:

  • Frame rendering stats para acompanhar a taxa de frames;
  • Paint flashing para ver regiões repintadas;
  • Layer borders para inspecionar camadas;
  • Scrolling performance issues para movimento ligado à rolagem.

Paint flashing transforma uma suspeita vaga em algo visível. Se uma pequena pulsação faz a página inteira piscar, investigue por que o dano de pintura ficou tão amplo.

O FPS é um sinal, não uma meta isolada. Uma animação pode parecer fluida no notebook e falhar sob CPU reduzida. Registre o cenário usado na comparação.

Troque movimento geométrico por transform

Para deslocar, rotacionar ou redimensionar visualmente um elemento, comece com transform.

Antes:

@keyframes enter-card {
from {
left: -24px;
}
to {
left: 0;
}
}

Depois:

@keyframes enter-card {
from {
transform: translateX(-24px);
}
to {
transform: translateX(0);
}
}

Para aparecer e desaparecer, use opacity quando a transição visual permitir.

O guia do web.dev para animações CSS de alta performance recomenda limitar animações a transform e opacity quando possível. A mesma página pede que will-change seja usado com parcimônia e somente depois de encontrar um problema.

Uma escala visual não muda o espaço reservado no layout. Se o conteúdo realmente precisa empurrar o que vem depois, talvez layout seja parte necessária do comportamento. Nesse caso, reduza a região afetada e a frequência, em vez de fingir que o espaço não mudou.

Não aplique will-change em tudo

will-change avisa o navegador que uma propriedade deve mudar e pode antecipar preparação de camada. Manter esse aviso em dezenas de elementos aumenta memória e pode piorar rasterização.

Use apenas quando o trace mostrar benefício:

.dialog[data-opening="true"] {
will-change: transform, opacity;
}

Remova o estado quando a transição terminar. Não espalhe will-change: transform por cards, ícones e seções que talvez nunca se movam.

Confirme no painel Performance se a animação passou à composição e se a quantidade de camadas continuou razoável.

Corte efeitos contínuos sem função

Movimento infinito tem custo durante todo o tempo em que a aba está visível. Também compete com leitura e interação.

Questione:

  • o brilho pulsante comunica estado ou só decora?
  • o parallax ajuda a entender a oferta?
  • três fundos animados precisam rodar ao mesmo tempo?
  • o carrossel precisa avançar sem ação?
  • o efeito pode parar fora da viewport?
  • a animação precisa continuar depois da primeira execução?

Remova o que não comunica mudança, progresso, relação espacial ou feedback. Para efeitos necessários, pare quando o elemento sair da viewport ou quando a aba ficar oculta, e teste a retomada.

Não introduza um IntersectionObserver complexo para economizar uma animação que poderia simplesmente não existir.

Faça JavaScript acompanhar o frame certo

Animações dirigidas por JavaScript precisam coordenar mudanças visuais com o navegador. requestAnimationFrame agenda o callback antes da próxima pintura, mas não torna o código barato.

let latestY = 0;
let scheduled = false;
function update() {
hero.style.transform = `translateY(${latestY * 0.08}px)`;
scheduled = false;
}
window.addEventListener(
"scroll",
() => {
latestY = window.scrollY;
if (!scheduled) {
scheduled = true;
requestAnimationFrame(update);
}
},
{ passive: true },
);

Esse padrão limita atualizações a uma por frame. Ainda assim, um parallax pode ser desnecessário, causar desconforto ou manter trabalho contínuo no scroll. Compare com a versão sem efeito.

Evite ler geometria depois de escrever estilos no mesmo callback. O artigo sobre DOM e layout mostra como leituras e escritas intercaladas causam layout forçado.

Preserve o significado da interação

Velocidade não justifica remover feedback. Uma animação curta pode mostrar que um painel veio do botão acionado ou que uma ação terminou.

Preserve:

  • estado final claro;
  • foco no elemento correto;
  • aria-expanded e aria-hidden coerentes;
  • clique e teclado durante e depois da transição;
  • cancelamento quando a pessoa fecha antes do fim;
  • conteúdo utilizável se a animação não executar.

Não bloqueie o botão por toda a duração de um efeito decorativo. Atualize o estado acessível no momento correto. O evento animationend pode não ocorrer se o efeito for cancelado.

Respeite prefers-reduced-motion

prefers-reduced-motion: reduce informa que a pessoa pediu menos movimento no sistema. A preferência não existe para melhorar uma nota de performance. Ela reduz desconforto e risco para pessoas sensíveis a movimento.

.hero-art {
animation: float 6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.hero-art {
animation: none;
}
}

A referência do prefers-reduced-motion explica que movimentos amplos de escala e panorâmica podem ser gatilhos vestibulares. Remova movimento não essencial ou substitua por uma transição discreta que preserve a informação.

Não use uma regra global com !important sem testar estados. Alguns spinners e feedbacks dependem de uma alternativa visível. O checklist de acessibilidade ajuda a revisar o resultado além da taxa de frames.

Teste animações de entrada na carga inicial

Animações da hero podem atrasar a percepção do conteúdo mesmo quando o navegador já pintou o elemento. Se título, preço ou CTA começam invisíveis por 800 ms, a pessoa espera uma decisão estética.

Para conteúdo principal:

  • evite atrasos em cascata longos;
  • não deixe texto essencial em opacity: 0 aguardando JavaScript;
  • mantenha o estado inicial legível se o script falhar;
  • confirme que a imagem hero não perde prioridade;
  • compare LCP e tempo de renderização do elemento.

O guia de LCP da imagem hero cobre descoberta e prioridade. A animação adiciona uma questão diferente: quando o conteúdo já disponível se torna de fato visível.

Compare a mesma ação antes e depois

Faça uma alteração pequena e repita:

  1. o mesmo dispositivo ou desaceleração;
  2. a mesma URL e estado inicial;
  3. a mesma ação;
  4. a mesma duração de gravação;
  5. pelo menos três execuções;
  6. o teste com movimento reduzido.

Compare frames lentos e tempo em JavaScript, Style, Layout, Paint e Composite. Depois faça uma revisão visual em velocidade normal. Uma curva de easing estranha pode produzir trace melhor e interface pior.

Teste também toque, teclado, zoom e conteúdo longo. Trocar dimensões por transform pode recortar sombras, sobrepor texto ou mudar a área clicável percebida.

Republique e valide a URL final

No Site no Ar:

  1. chame get_context para o Site existente;
  2. inspecione HTML, CSS e JavaScript dentro de public/;
  3. altere os arquivos pelas file tools;
  4. confirme os assets e public/sitemap.xml;
  5. chame deploy com uma mensagem curta;
  6. acompanhe deploy_status até sucesso ou falha;
  7. grave a animação novamente na URL pública.

O contrato está na documentação de Publicação. Se houver domínio próprio, teste o hostname usado pelo público, com cache e integrações reais.

Prompt para revisar animações

Revise as animações desta landing page sem publicar ainda.
URL e Version: [URL e commit]
Efeitos prioritários: [menu, hero, cards, modal ou scroll]
Cenário: [dispositivo, viewport e CPU]
1. Grave cada efeito no painel Performance três vezes.
2. Separe JavaScript, Style, Layout, Paint e Composite.
3. Use Paint flashing e a trilha Animations para localizar o custo.
4. Remova movimento sem função antes de otimizar propriedades.
5. Prefira transform e opacity quando preservarem o comportamento.
6. Use will-change somente com evidência e em poucos elementos.
7. Teste teclado, foco e prefers-reduced-motion.
8. Compare a mesma ação antes de propor a republicação.

A correção termina quando o movimento deixa de disputar a tarefa principal. A pessoa entende o feedback, a página entrega os frames no cenário testado e quem pediu menos movimento recebe uma experiência estável.