Performance: reflow, repaint e composite
Por que algumas animações travam e outras são suaves? A diferença está em qual parte do pipeline de renderização é acionada — e como evitar as mais custosas.
A diferença entre 60fps e 6fps
O browser tenta renderizar a 60 frames por segundo — um novo frame a cada 16ms. Se uma operação JavaScript ou CSS levar mais que isso, o frame é perdido e o usuário sente "jank" (travamento). A maioria das travagens acontece por reflow desnecessário: mudanças que forçam o browser a recalcular posições e tamanhos de elementos.
Entender quais propriedades CSS e quais operações JS disparam cada fase do pipeline é a
diferença entre uma animação fluida e uma que trava. A regra de ouro:
use transform e opacity para animações — elas
vão direto para a GPU.
setTimeout(fn, 0) ou scheduler.yield() para ceder
o thread periodicamente.
Explore o custo de cada propriedade
Clique nas categorias e depois nas propriedades para ver o que cada uma dispara no pipeline de renderização e por quê.
Estas propriedades são processadas inteiramente na GPU pelo thread do compositor, sem acionar o thread principal do browser. Animações a 60fps são alcançáveis.
Forced Synchronous Layout
// Forced Synchronous Layout — o pior anti-pattern // ✗ MAU: leitura depois de escrita em loop = reflow por iteração const elements = document.querySelectorAll(".card"); for (const el of elements) { el.style.width = el.offsetWidth + 10 + "px"; // read → reflow → write, 100x! } // ✓ BOM: leia tudo, depois escreva tudo (batch reads/writes) const widths = Array.from(elements).map(el => el.offsetWidth); // leitura em batch elements.forEach((el, i) => el.style.width = widths[i] + 10 + "px"); // escrita em batch // Melhor ainda: FastDOM (biblioteca) agenda leituras/escritas no frame certo
Ferramentas de diagnóstico
# Ferramentas para medir performance # 1. Performance API (JavaScript) performance.now() # timestamp de alta resolução (ms) performance.mark("inicio") performance.mark("fim") performance.measure("duracao", "inicio", "fim") # 2. PerformanceObserver (métricas automáticas) new PerformanceObserver((list) => { list.getEntries().forEach(e => console.log(e.name, e.startTime)); }).observe({ type: "layout-shift", buffered: true }); # 3. DevTools Performance tab # F12 → Performance → Record → interagir → Stop # Identifica: Long Tasks (>50ms), Layout, Paint, Script # 4. Lighthouse (DevTools → Lighthouse) # Pontuação 0-100 para Performance, Acessibilidade, SEO # Mostra oportunidades específicas de melhoria
fastdom (npm) automatiza esse padrão com uma API de agendamento.
Meça e otimize uma animação
Mini projeto: crie uma animação de 50 divs voando pela tela usando setInterval + left/top. Meça o FPS com performance.now(). Depois reimplemente com requestAnimationFrame + transform e compare.
Projeto principal: grave um perfil de performance no DevTools de uma página com scroll. Identifique a maior Long Task. Reescreva o código responsável para não bloquear o thread principal por mais de 16ms.
Desafio extra: use o Layout Instability API e o Largest Contentful Paint observer para criar um "Performance HUD" — um overlay que mostra LCP, CLS e FPS em tempo real sobre qualquer página, usando apenas um content script de extensão.
Teste sua intuição
Onde você encontra isso
Framer Motion
Biblioteca de animações do React que usa exclusivamente transform e opacity para animações de layout. Internally usa o FLIP technique (First, Last, Invert, Play) para animar mudanças de posição sem reflow.
Charts e D3
D3.js pode ser lento com muitos elementos SVG. O padrão moderno é usar WebGL (via regl ou Three.js) para renderizar grandes quantidades de dados diretamente na GPU, bypassing o pipeline DOM completamente.
INP (Interaction to Next Paint)
A nova métrica Core Web Vital mede o tempo desde um clique/teclado até o próximo pixel na tela. Um INP ruim (>200ms) quase sempre tem Long Tasks bloqueando o thread entre o evento e o render.
CSS Containment
contain: strict diz ao browser que mudanças dentro do elemento não afetam elementos fora. Isso limita o escopo do reflow a uma subárvore — crucial para componentes reutilizáveis em páginas grandes.