Motion performático com Claude Code: 60fps, reduced-motion e Core Web Vitals (com case aino.agency)
Motion performático com Claude Code: regra transform e opacity, reduced-motion em camadas, Lenis sem piorar INP, auditoria com MCPs e case aino.agency.
- motion performance 60fps acessibilidade
- 60fps transform opacity

Sumário
- Por que motion perde 60fps e piora Core Web Vitals?
- Como isolar transform e opacity com Claude Code?
- Como respeitar prefers-reduced-motion em camadas?
- Como acertar Lenis sem piorar INP?
- O que o case aino.agency prova sobre pouco JS?
- Como auditar motion com Playwright MCP, Chrome DevTools MCP e Context7?
- Quando remover animação em vez de otimizar?
- Perguntas frequentes sobre performance e reduced-motion
- Conclusão: regra, ramo reduce e auditoria antes de publicar
- Fontes
Motion quebra publicação em três pontos previsíveis. O scroll perde fluidez porque a propriedade errada recalcula layout a cada frame. A página desloca porque pin e reveal entram sem espaço reserva. Parte do público recebe animação que pediu para não ver, porque falta alternativa estática para prefers-reduced-motion.
Este guia trata esses três pontos como critério de aceite, com regra de propriedade, ramo reduce em camadas, acerto de Lenis com INP sob controle e auditoria no navegador com comandos e prompts prontos para Claude Code. Para o mapa das bibliotecas e a regra de decisão por trabalho, volte ao guia completo de motion.
Por que motion perde 60fps e piora Core Web Vitals?
Propriedade errada custa frame, layout e resposta. Transform e opacity passam por composição, sem recalcular caixa nem repintar camada inteira. Top, left, width, height e margin disparam reflow, que recalcula posição e tamanho e derruba a taxa de frames em lista longa e scroll com pin. Essa é a regra estável da skill 60fps-animation do repositório iart-ai, segundo repo iart-ai.
O vínculo com Core Web Vitals é direto. LCP piora quando hero animado atrasa o maior conteúdo visível. CLS piora quando pin entra sem espaço reserva ou quando reveal troca altura sem placeholder. INP piora quando smooth com inércia, listener pesado e animação longa atrasam a resposta ao clique e ao toque. A análise de libs com tabela React e Next.js, que liga Lenis, lerp e INP, aparece em snigdha de 18/jun/2026.
A correção começa antes do código, com três limites. Duração curta para confirmação de gesto. Espaço reserva para todo pin e reveal. Nenhum conteúdo essencial preso a movimento sem alternativa. Esses limites viram checklist auditável na seção de auditoria, com verificação por LCP, CLS e INP no navegador.
O que medir antes de otimizar
Meça LCP no hero, CLS em pins e reveals e INP em botões e filtros com animação. Se LCP sobe com intro, se CLS sobe com pin ou se INP sobe com smooth, o problema está na arquitetura do motion, não em micro ajuste de easing.
Como isolar transform e opacity com Claude Code?
A skill define o padrão e o prompt trava a execução. A skill 60fps-animation do conjunto iart-ai orienta padrão 60fps com transform e opacity, com exemplos de hero, transição e micro-interação sem reflow, segundo repo iart-ai. Sem essa trava, o modelo mistura top com translate e width com scale, o que cria duas fontes de verdade para o mesmo movimento.
O prompt funciona melhor com proibição explícita. Descreva componente, propriedade permitida e propriedade vetada, com duração e easing centralizados. Um exemplo direto para hero é: "Build this hero animation using only transform and opacity, no top, left, width or height animation." Depois complete com seletores, valores de translate e scale e comportamento em mobile. Para micro-interação em React, o complemento é layout com transform, como mostra a documentação de layout em motion.dev.
// Permitido: composição sem reflow
gsap.to(".card", { x: 24, scale: 1.04, opacity: 1, duration: 0.28, ease: "power2.out" });
// Vetado neste guia: recalcula layout
// gsap.to(".card", { left: 24, width: 320 });Centralize tokens de duração e easing em um arquivo. Duração curta para hover e press, média para entrada de seção e nenhuma timeline longa para confirmação de clique. Quando o Claude Code recebe tokens prontos, ele para de inventar curva por seção e o motion ganha ritmo consistente.
Como respeitar prefers-reduced-motion em camadas?
Toda animação relevante precisa de equivalente estático legível. A base legal e técnica é WCAG 2.3.3, que trata animação disparada por interação e pede mecanismo para desativar movimento não essencial. A skill accessible-animation do mesmo repositório iart-ai organiza isso em modelo tiered, com níveis de redução por severidade em vez de tudo ou nada, segundo repo iart-ai.
O dado de alcance explica por que esse ramo não é detalhe. Mais de 50% dos sites mobile já tratavam prefers-reduced-motion em 2024, em leitura do Web Almanac citada via annnimate. Com adoção nesse patamar, publicar sem ramo reduce é publicar fora do padrão que metade da web mobile já segue.
Com GSAP, a divisão usa gsap.matchMedia. Um ramo atende no-preference com pin, scrub e parallax completos. Outro ramo atende reduce com conteúdo visível, sem pin nem scrub.
import gsap from "gsap";
const mm = gsap.matchMedia();
mm.add("(prefers-reduced-motion: no-preference)", () => {
// pin, scrub e parallax completos aqui
});
mm.add("(prefers-reduced-motion: reduce)", () => {
gsap.set(".pinned-hero, .reveal, .layer-back", { clearProps: "all", opacity: 1, y: 0 });
});Com Motion em React, a divisão usa MotionConfig com reducedMotion="user" e o hook useReducedMotion para bifurcar variantes. O padrão aparece na documentação em motion.dev e segue a mesma lógica do matchMedia, com versão estática sem perda de informação.
import { MotionConfig, motion, useReducedMotion } from "motion/react";
export function RevealCard() {
const reduce = useReducedMotion();
return (
<MotionConfig reducedMotion="user">
<motion.div
initial={{ opacity: 0, y: reduce ? 0 : 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
/>
</MotionConfig>
);
}O modelo tiered fecha o ciclo. Nível um remove parallax e scrub. Nível dois remove autoplay e loop. Nível três congela transições em corte seco com conteúdo completo. Cada nível mantém hierarquia e leitura, sem esconder preço, CTA ou feedback de formulário.
Como acertar Lenis sem piorar INP?
Lenis dá inércia ao scroll, mas inércia sem limite atrasa resposta. O parâmetro lerp controla a suavização, com faixa citada entre 0.05 e 0.15: valor baixo dá scroll mais solto e resposta mais lenta, valor alto dá scroll mais direto e resposta mais rápida. A análise que liga essa faixa a INP em stack React e Next.js aparece em snigdha de 18/jun/2026, com o padrão de sincronia lenis.on(scroll, ScrollTrigger.update) descrito também em youngju.dev de 16/mai/2026 e em adamarant de 28/mai/2026.
Para quem prefere menos movimento, a saída é parar o smooth. A chamada lenis.stop congela a inércia e devolve scroll nativo, o que preserva leitura e resposta para o ramo reduce. Combine com matchMedia para ligar e desligar o Lenis junto com pin e scrub.
import Lenis from "lenis";
import { ScrollTrigger } from "gsap/ScrollTrigger";
const lenis = new Lenis({ lerp: 0.1 });
lenis.on("scroll", ScrollTrigger.update);
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
lenis.stop();
}Para a base completa de pin, scrub e parallax com essa ponte, com raf no ticker do GSAP e lagSmoothing zerado, revise o scroll cinematográfico com GSAP e Lenis. A regra prática para INP é testar a faixa com clique real em filtro e menu: se o valor baixo atrasa confirmação, suba o lerp ou desligue o smooth nessa rota e meça de novo.
O que o case aino.agency prova sobre pouco JS?
Aino.agency mostra que restrição com direção gera identidade. O site, SOTD na seleção de animação do Awwwards, usa ASCII como textura e física simples em vanilla, com página total de 30kb de JS. Nenhum framework de animação carrega a página. O movimento responde a cursor e scroll com poucas linhas, e a leitura segue por hierarquia clara.
O padrão útil está na economia. Uma técnica de textura, no caso ASCII, mais uma física curta para resposta ao gesto. Sem vídeo de fundo, sem loop concorrente, sem pin sobre texto denso. Cada seção pede um gesto e devolve uma mudança visível, o que mantém atenção sem custo de bundle.
A lição para Claude Code é de escopo, não de ferramenta. Peça textura com pouco custo e física curta em vanilla quando a identidade permite. Reserve GSAP, Motion e runtime vetorial para scroll com narrativa, micro-interação com estado e vetor com inputs. Quando pouco JS resolve, pouco JS é a stack correta.
Como auditar motion com Playwright MCP, Chrome DevTools MCP e Context7?
Auditoria no navegador decide o que fica no ar. O fluxo usa Playwright MCP para navegação e medição, Chrome DevTools MCP para performance e Context7 para conferir docs atuais antes de corrigir API. A organização desse trio, com frontend-design, coleção de skills e Figma MCP para handoff, aparece no toolkit frontend para Claude Code.
O Playwright MCP roda com visão automática e com capacidade de DevTools para LCP, CLS e INP, via pacote @playwright/cli. O Chrome DevTools MCP completa com timeline e trace de performance. O Context7 confere assinatura atual de GSAP, Motion e Lenis antes de gerar correção longa.
npx -y @playwright/cli install --with-deps
npx -y @playwright/cli test --vision auto --caps=devtoolsOs prompts de auditoria funcionam melhor literais e com saída por arquivo e linha. Dois prompts cobrem o ciclo:
"Audit this page for transform-only animations, CLS from pins and reveals, INP from smooth scroll and long transitions, and prefers-reduced-motion coverage. Report file, line, failing metric and fix."
"Generate a reduced-motion variant for every animated section with static equivalents, no pin, no scrub and no autoplay, following WCAG 2.3.3. Keep headings, CTAs and form feedback fully visible."
A tabela abaixo resume o checklist. Cada linha traz problema visível, causa provável, correção direta e verificação no navegador. Ela funciona como Definition of Done antes do deploy.
| Problema | Causa | Correção | Verificação |
|---|---|---|---|
| Jank em lista e scroll | Animação de top, left, width ou height com reflow | Trocar por transform e opacity com duração curta | Timeline sem reflow no Chrome DevTools MCP e scroll sem salto no Playwright MCP |
| CLS em pin e reveal | Pin sem espaço reserva e reveal sem placeholder | Reservar altura do pin e placeholder do reveal | CLS zerado em reload com --caps=devtools e teste em viewport mobile |
| INP alto em clique e filtro | Lerp baixo com inércia longa e transição longa | Subir lerp na faixa 0.05 a 0.15 ou desligar smooth na rota | INP dentro do limite em teste com clique real via @playwright/cli |
| Animação sem alternativa | Falta de ramo reduce para prefers-reduced-motion | Adicionar matchMedia com reduce e MotionConfig reducedMotion="user" | Teste com reduce ativo mostra conteúdo estático completo e lenis.stop aplicado |
| Autoplay fora da dobra | Player e loop ativos sem IntersectionObserver | Pausar fora da viewport e dar play só na entrada | Nenhum canvas ativo fora da dobra durante scroll no trace |
| Loop que distrai de formulário | Movimento contínuo perto de input e CTA | Remover loop na zona de formulário e manter foco visível | Formulário completa sem distração e sem perda de feedback |
Quando remover animação em vez de otimizar?
Algumas animações não merecem ajuste fino. Intro longa que atrasa LCP, parallax que compete com parágrafo, loop ao lado de formulário e transição que esconde confirmação de clique entram nessa lista. O critério é de tarefa: se o motion atrasa leitura, confunde estado ou consome atenção sem explicar mudança, a correção é remover e medir leitura de novo.
Aplica-se o mesmo rigor a vetor interativo. Loop sem gesto, Rive concorrente em toda a página e triggers sem hierarquia viram ruído e derrubam leitura. Para a decisão por inputs, com Rive para estados e dotLottie para loops leves, revise o Rive vs Lottie com Claude Code. Se o vetor não muda de estado com gesto, troque autoplay por play na entrada ou remova a instância e congele no frame inicial.
Remover também simplifica auditoria. Menos timelines para medir, menos ramos reduce para manter e menos JS para carregar. Em página com orçamento estourado, remoção com motivo vale mais que otimização sem critério.
Perguntas frequentes sobre performance e reduced-motion
Por que só transform e opacity seguram 60fps?
Porque passam por composição sem recalcular caixa. Top, left, width e margin disparam reflow e repintura, o que custa frames em scroll e lista. A skill 60fps-animation do repo iart-ai fixa esse padrão com exemplos de hero e micro-interação sem reflow.
Como desligo Lenis e scrub para quem prefere menos movimento?
Use gsap.matchMedia com ramo reduce, chame lenis.stop e entregue conteúdo estático com opacity 1 e sem pin. Em React, some MotionConfig reducedMotion="user" com useReducedMotion para bifurcar variantes, segundo motion.dev. O padrão de Lenis com reduced-motion aparece em adamarant de 28/mai/2026.
Como audito LCP, CLS e INP com Playwright MCP?
Rode o pacote @playwright/cli com --vision auto e --caps=devtools para capturar LCP, CLS e INP durante navegação, e complete com Chrome DevTools MCP para timeline. O fluxo com esses MCPs e Context7 para docs aparece no toolkit frontend para Claude Code.
Quando vale remover motion em vez de otimizar?
Quando atrasa tarefa, confunde estado ou compete com leitura sem explicar mudança. Intro longa sobre LCP, parallax sobre texto e loop perto de formulário são candidatos diretos. Remova, meça LCP, CLS e leitura de novo e só reintroduza com motivo e com ramo reduce.
Conclusão: regra, ramo reduce e auditoria antes de publicar
Motion performático pede três acertos em sequência. Regra transform e opacity para segurar 60fps sem reflow. Ramo reduce em camadas com matchMedia, MotionConfig e lenis.stop, em modelo tiered ligado a WCAG 2.3.3 e à adoção em 50%+ dos sites mobile. Lenis com lerp entre 0.05 e 0.15 e INP medido com clique real. O case aino.agency, SOTD com ASCII e física em vanilla e 30kb de JS total, mostra que restrição com direção sustenta prêmio. A auditoria com Playwright MCP, Chrome DevTools MCP e Context7 fecha o ciclo com comandos e prompts literais.
O próximo passo depende do gargalo. Para scroll com pin e parallax, volte ao satélite de GSAP com Lenis. Para vetor com estados, avance para o comparativo entre Rive e Lottie. Para o mapa geral, volte ao pilar e decida o que fica no ar.
Fontes
Leia também
Motion •
Rive vs Lottie com Claude Code: animação com state machine (com case Razorpay Sprint26)
Comparativo Rive vs Lottie com Claude Code: state machine com inputs, dotLottie mais leve, tabela de decisão, integração com runtime em React e web, prompts prontos e case Razorpay Sprint26.
- rive vs lottie claude code
- rive state machine animação
Motion •
Micro-interações com Motion no Claude Code: layout, gestures e AnimatePresence (com case Waabi)
Micro-interações com Motion no Claude Code: layout, gestures, shared element com layoutId e AnimatePresence, prompts prontos e case Waabi.
- motion framer micro interações claude code
- motion layout animatepresence
Motion •
Scroll cinematográfico com GSAP + Lenis no Claude Code: pin, scrub e parallax (com cases Oryzo AI e Studio K95)
Tutorial de scroll cinematográfico com GSAP ScrollTrigger e Lenis no Claude Code: pin, scrub, parallax, decisão ScrollSmoother vs Lenis, prompts prontos e cases Oryzo AI e Studio K95.
- gsap scrolltrigger lenis claude code
- gsap scroll pin scrub parallax


