Animação CSS avançada com Claude Code: performance, acessibilidade e testes
Guia prático para criar animações CSS rápidas, acessíveis e verificáveis com Claude Code.
Animação CSS precisa de intenção, não só movimento
Claude Code consegue gerar um fade, slide ou skeleton em poucos segundos. O desafio real é fazer essa animação funcionar em produção: ela deve explicar o que mudou, não roubar atenção; deve ser rápida, não pesada; e precisa respeitar pessoas que configuraram o sistema para reduzir movimentos.
Este guia olha para animação CSS avançada pelo lado da implementação. Vamos cobrir transition versus keyframes, por que transform e opacity costumam ser as propriedades mais seguras, o que é layout thrash, como usar prefers-reduced-motion, como criar animações de entrada e ligadas ao scroll, quando skeleton states ajudam, como expressar movimento em tokens de design, como pedir uma revisão crítica ao Claude Code e como validar com Playwright.
Algumas definições simples: transition é a interpolação entre dois estados, como um botão em hover. Keyframes descreve uma linha do tempo com etapas como 0%, 60% e 100%. Layout thrash acontece quando o navegador recalcula tamanho e posição várias vezes. Tokens de movimento são valores nomeados, como --motion-duration-fast, usados para manter duração, easing e distância consistentes.
Para contexto adicional, veja também otimização de performance com Claude Code, variáveis CSS com Claude Code e acessibilidade com Claude Code.
Escolha transition ou keyframes conscientemente
Use transitions para pequenas mudanças de estado: hover, focus, active, selected, expanded ou disabled. Use keyframes quando o caminho intermediário importa: entrada de painel, loop de carregamento, aviso em etapas, progresso de leitura ou reveal no scroll.
Essa decisão deve aparecer no prompt para Claude Code. Se você pedir apenas “deixe mais animado”, o CSS gerado pode animar top, left, height ou margin. Essas propriedades podem forçar recálculo de layout e gerar travamentos visuais. Uma instrução melhor é: transition para estados interativos, keyframes para linha do tempo e prioridade para transform e opacity.
:root {
--motion-duration-fast: 160ms;
--motion-duration-normal: 280ms;
--motion-ease-standard: cubic-bezier(0.2, 0, 0, 1);
--motion-distance-sm: 12px;
}
.button {
transition:
background-color var(--motion-duration-fast) var(--motion-ease-standard),
transform var(--motion-duration-fast) var(--motion-ease-standard);
}
.button:hover {
transform: translateY(-2px);
}
.notice {
opacity: 0;
transform: translateY(var(--motion-distance-sm));
animation: notice-enter var(--motion-duration-normal) var(--motion-ease-standard) forwards;
}
@keyframes notice-enter {
from {
opacity: 0;
transform: translateY(var(--motion-distance-sm));
}
to {
opacity: 1;
transform: translateY(0);
}
}
O botão usa transition porque responde a um estado direto. O aviso usa keyframes porque tem uma entrada desenhada. Para confirmar detalhes, consulte as referências oficiais da MDN sobre CSS animations e transform.
Performance começa com transform e opacity
O navegador produz cada frame passando por layout, paint e composição. Layout calcula geometria, paint desenha pixels e composição combina camadas. Animar transform e opacity geralmente fica na composição, por isso costuma ser mais suave.
Animar width, height, margin, top ou left pode afetar elementos vizinhos. Se JavaScript também lê medidas e escreve estilos em sequência, surge layout thrash. Em componentes React, mantenha a classe de animação simples e testável.
import type { ReactNode } from "react";
import "./motion.css";
type AnimatedPanelProps = {
children: ReactNode;
isOpen: boolean;
};
export function AnimatedPanel({ children, isOpen }: AnimatedPanelProps) {
return (
<section
className={isOpen ? "panel panel-enter" : "panel"}
aria-hidden={!isOpen}
>
{children}
</section>
);
}
.panel {
opacity: 0;
transform: translateY(12px) scale(0.98);
pointer-events: none;
}
.panel-enter {
animation: panel-enter 220ms cubic-bezier(0.2, 0, 0, 1) forwards;
pointer-events: auto;
}
@keyframes panel-enter {
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
Use will-change com cuidado. Ele pode ajudar pouco antes da animação, mas deixá-lo em muitos elementos consome memória. O guia da web.dev sobre performance de animações mostra por que a propriedade escolhida para animar importa tanto.
Casos de uso práticos
Primeiro caso: animação de entrada para cards, tabelas de preço ou módulos de dashboard. Uma entrada curta guia o olhar. Uma sequência lenta em todos os cards apenas atrasa a leitura. Mantenha delays pequenos e garanta que o conteúdo continue visível sem animação.
Segundo caso: feedback ligado ao scroll, como barra de progresso de leitura ou reveal de seções. animation-timeline é útil, mas precisa de fallback. Se o navegador não suportar, a página ainda deve ser legível.
.scroll-progress {
position: fixed;
inset: 0 auto auto 0;
z-index: 20;
width: 100%;
height: 3px;
transform-origin: left;
transform: scaleX(0);
background: var(--color-accent, #2563eb);
}
@supports (animation-timeline: scroll()) {
.scroll-progress {
animation: progress-grow linear both;
animation-timeline: scroll();
}
}
@keyframes progress-grow {
to {
transform: scaleX(1);
}
}
.reveal {
opacity: 1;
transform: none;
}
@supports (animation-timeline: view()) {
.reveal {
opacity: 0;
transform: translateY(16px);
animation: reveal-up 1ms linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
}
@keyframes reveal-up {
to {
opacity: 1;
transform: translateY(0);
}
}
Terceiro caso: skeleton e estados de carregamento. Um skeleton reduz a incerteza, mas shimmer forte por muito tempo cansa. Para operações longas, adicione texto de status, tentar novamente ou cancelar.
Quarto caso: feedback operacional em SaaS. Salvo com sucesso, filtro aplicado, item movido ou painel de erro aberto são bons candidatos a animações curtas. Em telas usadas repetidamente, estabilidade é mais importante do que impacto visual.
Respeite reduced motion e saiba quando não animar
prefers-reduced-motion permite responder à preferência do usuário por menos movimento. Isso não é opcional: algumas pessoas sentem desconforto, fadiga ou distração com animações fortes. A referência oficial da MDN sobre prefers-reduced-motion explica o uso correto.
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
animation-duration: 1ms !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-duration: 1ms !important;
}
.scroll-progress {
animation: none;
transform: scaleX(1);
}
.skeleton {
animation: none;
background-image: none;
}
}
Também há lugares em que não animar é melhor: confirmação de pagamento, textos legais, erros críticos de formulário, leitura longa, tabelas densas e menus abertos muitas vezes por dia. Nesses casos, clareza imediata vence qualquer efeito.
Use Claude Code como revisor
Não peça apenas para adicionar movimento. Peça para revisar riscos. Este prompt funciona como checklist:
Review and improve the CSS animation implementation for this UI.
Requirements:
- Use transition for simple hover/focus/open states.
- Use keyframes only when intermediate timing matters.
- Animate transform and opacity first; avoid top, left, width, height, and margin animations.
- Add design tokens for duration, easing, and distance.
- Respect prefers-reduced-motion.
- Keep content visible when scroll-linked animation is unsupported.
- Do not animate critical form errors, payment confirmation, or long reading content.
Return:
1. Risky selectors and why they are risky.
2. A corrected CSS/React implementation.
3. Manual and Playwright checks to verify overflow and reduced motion.
Assim Claude Code tende a encontrar layout thrash, loops infinitos, excesso de will-change, fallback ausente e preferência de movimento ignorada.
Verifique com Playwright
Falhas de animação costumam ser visuais. Adicione checks focados para overflow horizontal, conteúdo visível e comportamento com reduced motion.
import { expect, test } from "@playwright/test";
test("animated page has no horizontal overflow", async ({ page }) => {
await page.goto("/animation-demo");
const overflow = await page.evaluate(() => {
return document.documentElement.scrollWidth > window.innerWidth;
});
expect(overflow).toBe(false);
});
test("reduced motion keeps content visible", async ({ browser }) => {
const context = await browser.newContext({ reducedMotion: "reduce" });
const page = await context.newPage();
await page.goto("/animation-demo");
await expect(page.locator(".reveal").first()).toBeVisible();
await expect(page.locator(".skeleton").first()).toHaveCSS("animation-name", "none");
await context.close();
});
Em telas críticas, inclua comparação de screenshots em desktop e mobile. O teste não substitui julgamento de design, mas encontra conteúdo escondido, rolagem horizontal e reduced motion ignorado.
Resumo e próximo passo
Animação CSS de produção começa com intenção. Use transition para estados simples, keyframes para linhas do tempo, transform e opacity para movimento fluido, tokens para consistência, reduced motion para acessibilidade e Playwright para validação visual. Claude Code funciona melhor quando recebe essas restrições.
Como próximo passo, escolha uma lista de cards ou seção CTA existente e aplique os tokens, a entrada animada, a regra reduced motion e os testes deste artigo. Para uma revisão mais completa, veja treinamento e consultoria.
Nota de verificação prática: limitando o movimento a transform e opacity, não apareceu overflow horizontal. No Playwright com reduced motion, o conteúdo .reveal continuou visível e o skeleton ficou sem animação. Em telas operacionais, shimmer longo pareceu tornar a espera maior; um placeholder discreto costuma funcionar melhor.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Permission receipt no Claude Code: escopo, prova e rollback
Padrão de permission receipt para Claude Code: ações permitidas, limites de aprovação, comandos de prova, rollback e CTA de receita.
Agent Harness seguro para Claude Code e Codex: permissoes, verificacao e rollback
Monte uma base segura para agentes com Claude Code e Codex usando politicas, plano, verificacao e recuperacao.
Subagentes no Claude Code: guia prático para delegar trabalho com segurança
Guia prático de subagentes no Claude Code para dividir artigos e código: regras, prompts, riscos e checklist.