Ferramenta
Animações de interface para copiar
36 peças originais com preview ao vivo. 32 delas são CSS puro — copia e usa, sem instalar nada. As outras 4 usam biblioteca porque fazem algo que folha de estilo não faz: cascata calculada, contagem de número, contorno de SVG.
Cada peça traz o comentário do porquê no próprio código: qual propriedade é barata de animar, onde o layout é recalculado e o que quebra em tela pequena.
O bloco sobe alguns pixels enquanto aparece. Sugere que veio de fora da tela, sem chamar atenção para si.
<div class="surgir">Conteúdo carregado</div>O conteúdo entra desfocado e ganha nitidez. Bom para imagem ou destaque — mas custa caro, use uma vez por tela.
<div class="foco">Imagem em destaque</div>Uma faixa varre o bloco e revela o conteúdo. Usa clip-path, então não precisa de elemento extra por cima.
<div class="cortina">Revelado</div>Lista aparecendo item a item, com atraso crescente. É o caso clássico em que uma biblioteca economiza trabalho de verdade.
<ul class="cascata">
<li>Primeiro item</li>
<li>Segundo item</li>
<li>Terceiro item</li>
<li>Quarto item</li>
<li>Quinto item</li>
</ul>O bloco cresce da altura zero até o tamanho natural. Mostra na prática por que animar altura é a opção cara.
<div class="abrir">
<div class="abrir__conteudo">Este painel abriu animando a altura</div>
</div>O conteúdo aparece por baixo de uma cortina que sobe. Usa clip-path, então não precisa de máscara nem overflow.
<div class="cortina">Conteúdo revelado</div>O cartão tomba para frente até assentar. Um perspective no pai dá a profundidade.
<div class="flip-wrap"><div class="flip-card">Novo cartão</div></div>O texto entra desfocado e ganha nitidez. Bom para um título que precisa de um instante de atenção.
<h3 class="foco">Interface nítida</h3>Os itens entram um a um, sem biblioteca — cada linha atrasa a própria animação com nth-child.
<ul class="cascata">
<li>Primeiro item</li>
<li>Segundo item</li>
<li>Terceiro item</li>
<li>Quarto item</li>
</ul>Um anel que se expande e some, marcando algo novo sem piscar na cara do usuário.
<button class="pulso">
Notificações
<span class="pulso__ponto"></span>
</button>O campo balança de leve ao rejeitar um valor. Comunica erro antes de a pessoa ler a mensagem.
<input class="recusa" value="email-invalido" readonly />Uma faixa de luz atravessa o botão. Funciona no CTA principal — e só nele.
<button class="brilho">Começar agora</button>O valor sobe de zero até o total. CSS não interpola texto — aqui a biblioteca resolve o que folha de estilo não faz.
<div class="contador">
<span class="contador__valor">0</span>
<span class="contador__rotulo">assinantes</span>
</div>A etiqueta entra girando e assenta. Marca item novo numa lista sem precisar de cor berrante.
<div class="selo-caixa">
<span class="selo">novo</span>
Plano Pro
</div>O campo balança de leve para sinalizar erro. Curto e horizontal — chama atenção sem parecer defeito.
<input class="campo-erro" value="senha incorreta" readonly />Um anel se expande e some em volta do ponto. Guia o olho para uma novidade sem mover o elemento.
<button class="pulso">Novidade</button>Um reflexo cruza o elemento, como luz passando. Bom para destacar um selo ou botão premium.
<span class="varre">Plano Pro</span>O coração dá dois batimentos e volta. Confirma a curtida com um gesto que a gente reconhece.
<span class="bate" role="img" aria-label="curtido">♥</span>O indicador mais discreto que existe. Cabe dentro de botão e ao lado de texto sem quebrar o alinhamento.
<div class="pontos" role="status" aria-label="Carregando">
<span></span><span></span><span></span>
</div>Para quando você não sabe quanto falta. Se souber a porcentagem, mostre a porcentagem — é sempre melhor.
<div class="barra" role="status" aria-label="Carregando">
<div class="barra__trilho"></div>
</div>Blocos cinzas no formato do que vem depois. Reduz a sensação de espera porque a página não pula quando o dado chega.
<div class="esqueleto" role="status" aria-label="Carregando conteúdo">
<div class="esqueleto__avatar"></div>
<div class="esqueleto__linhas">
<div class="esqueleto__linha"></div>
<div class="esqueleto__linha esqueleto__linha--curta"></div>
</div>
</div>Círculo que preenche conforme a porcentagem real. Usa o contorno tracejado do SVG como barra.
<div class="anel">
<svg viewBox="0 0 100 100" width="112" height="112">
<circle class="anel__fundo" cx="50" cy="50" r="42" />
<circle class="anel__frente" cx="50" cy="50" r="42" />
</svg>
<span class="anel__texto">0%</span>
</div>O spinner de sempre, em cinco linhas de CSS. Vale lembrar que ele não precisa de biblioteca nenhuma.
<div class="giro" role="status" aria-label="Carregando"></div>O contorno do conteúdo enquanto ele carrega, com um brilho que percorre. Reduz a sensação de espera.
<div class="esq">
<div class="esq__linha esq__linha--titulo"></div>
<div class="esq__linha"></div>
<div class="esq__linha esq__linha--curta"></div>
</div>Um arco que gira indefinidamente num SVG. O stroke-dasharray desenha só um pedaço do círculo.
<svg class="anelp" viewBox="0 0 50 50" width="52" height="52" role="img" aria-label="Carregando">
<circle class="anelp__trilho" cx="25" cy="25" r="20" />
<circle class="anelp__arco" cx="25" cy="25" r="20" />
</svg>Os pontos sobem em sequência, como o indicador de digitação de um chat. Cada ponto atrasa o próprio salto.
<div class="pontos" role="img" aria-label="Digitando">
<span></span><span></span><span></span>
</div>Um giro com gradiente cônico e centro vago — mais moderno que a bordinha girando. Usa mask para o furo.
<div class="conico" role="img" aria-label="Carregando"></div>Menu virando X ao abrir. As duas barras se cruzam em vez de sumir e aparecer.
<button class="menu" aria-label="Abrir menu">
<span class="menu__barra"></span>
<span class="menu__barra"></span>
<span class="menu__barra"></span>
</button>
<p class="menu__dica">passe o mouse</p>O marcador acompanha a aba ativa em vez de piscar no lugar novo. Dá continuidade à navegação.
<div class="abas">
<input type="radio" name="aba" id="a1" checked />
<input type="radio" name="aba" id="a2" />
<input type="radio" name="aba" id="a3" />
<label for="a1">Visão geral</label>
<label for="a2">Detalhes</label>
<label for="a3">Histórico</label>
<span class="abas__marcador"></span>
</div>O botão vira confirmação sem mudar de tamanho. Evita o pulo de layout que acontece quando o texto muda.
<button class="confirmar">
<span class="confirmar__estado confirmar__estado--antes">Salvar alterações</span>
<span class="confirmar__estado confirmar__estado--depois">Salvo ✓</span>
</button>
<p class="confirmar__dica">passe o mouse</p>As letras entram uma a uma. Precisa quebrar o texto em elementos antes — trabalho que a biblioteca já faz.
<h3 class="montar">Interface em movimento</h3>Duas faces no mesmo espaço, giradas em 3D. O truque está em esconder o verso.
<div class="virar">
<div class="virar__interno">
<div class="virar__face virar__face--frente">Frente</div>
<div class="virar__face virar__face--verso">Verso</div>
</div>
</div>
<p class="virar__dica">passe o mouse</p>A bolinha desliza com um leve exagero no fim. O overshoot dá a sensação física de um botão real.
<label class="sw">
<input type="checkbox" checked />
<span class="sw__trilho"><span class="sw__bola"></span></span>
</label>Uma onda cresce do centro ao acionar, o feedback tátil dos apps. Em uso real, dispare no :active ou no clique.
<button class="onda">Tocar</button>O círculo e o tique são traçados na hora do sucesso. stroke-dashoffset desenha cada caminho.
<svg class="visto" viewBox="0 0 52 52" width="72" height="72" role="img" aria-label="Concluído">
<circle class="visto__circ" cx="26" cy="26" r="24" />
<path class="visto__tique" d="M15 27 l8 8 l15 -16" />
</svg>O painel desliza para fora ao abrir, sem cortar seco. grid-template-rows anima de 0 a 1fr — o jeito atual de animar altura.
<div class="acc">
<label class="acc__cabeca">
<input type="checkbox" checked />
Como funciona? <span class="acc__seta">▾</span>
</label>
<div class="acc__corpo"><div class="acc__interno">O conteúdo aparece deslizando, com a altura animada de zero até o tamanho real.</div></div>
</div>A pergunta que vem antes de escolher o efeito
Movimento na interface tem função. Ele diz de onde um elemento veio, avisa que algo mudou, confirma que o clique foi registrado. Quando não faz nenhuma dessas coisas, ele só atrasa a pessoa que queria ler o conteúdo.
Antes de copiar qualquer peça daqui, responda: o que essa animação está comunicando? Se a resposta for "fica bonito", provavelmente ela não deveria existir naquele lugar. Vale especialmente para animação de entrada em página com muito texto — quem chegou para ler não quer esperar o parágrafo aparecer.
O sinal de que passou do ponto é fácil de reconhecer: você já viu a animação cinquenta vezes durante o desenvolvimento e ela começou a incomodar. Se incomoda quem construiu, incomoda quem usa todo dia.
Por que algumas propriedades travam e outras não
Esta é a parte técnica que muda mais o resultado, e quase nenhum tutorial explica.
Para desenhar um quadro, o navegador passa por três etapas: calcular onde cada elemento fica (layout), pintar os pixels (paint) e juntar as camadas na tela (composite). Animar uma propriedade obriga a refazer a partir da etapa que ela afeta — sessenta vezes por segundo.
- Barato:
transformeopacity. Só a última etapa. O navegador resolve sem recalcular nada, muitas vezes fora da linha principal. - Médio:
background-color,box-shadow,filter. Exigem repintura da região. - Caro:
width,height,top,left,margin,padding. Refazem o layout — e mexer num elemento pode obrigar a recalcular os vizinhos.
Por isso, dentro do acervo, quase toda peça se move com transform: translate() em vez de left, e cresce com scale() em vez de width. O efeito visual é o mesmo; o custo não.
Isso não significa que animar altura seja proibido — a peça "Abrir espaço" faz exatamente isso, porque um painel que expande precisa empurrar o conteúdo de baixo. A diferença é fazer por necessidade, uma vez na tela, e não por hábito em quarenta cards de uma lista.
Duração e curva: os dois números que definem a sensação
Duração. Quase sempre menor do que a intuição sugere. Entre 150 e 300 ms para transição de estado; até 500 ms para algo que entra em cena. Acima disso a pessoa espera a animação em vez de usar a interface — e num painel de trabalho, esperar meio segundo a cada clique vira irritação acumulada.
Um detalhe fácil de esquecer: a duração deve ser a mesma em todo o produto para o mesmo tipo de movimento. Velocidade inconsistente é percebida mesmo por quem não sabe nomear o problema.
Curva. Movimento linear parece mecânico, porque nada no mundo físico começa e para instantaneamente. A regra prática:
- Saindo (algo desaparece): comece rápido. A pessoa já decidiu, não precisa acompanhar.
- Entrando (algo aparece): termine devagar. Dá tempo de o olho encontrar o elemento.
- Rotação contínua (um spinner): linear é o certo — não há começo nem fim para acentuar.
Curvas que passam do valor final e voltam dão sensação de peso físico. Funcionam bem em elemento pequeno que aparece, como um selo ou um ícone. Em bloco grande, parecem instáveis.
Acessibilidade não é opcional aqui
Existe gente que sente desconforto físico real com movimento na tela — náusea, tontura, dor de cabeça. Não é preferência estética: é condição médica, e o sistema operacional já expõe essa configuração.
Respeitar custa uma media query, e todas as peças deste acervo já vêm com ela:
- Desligue o que é decorativo — brilho, pulso, entrada.
- Reduza, em vez de remover, o que comunica estado. Um spinner precisa continuar girando, só mais devagar; sem ele, a pessoa não sabe que o sistema está trabalhando.
O outro ponto: indicador de carregamento precisa de role="status" e um rótulo. Sem isso, quem usa leitor de tela não recebe aviso nenhum — a tela simplesmente fica em silêncio enquanto a página trabalha. É a falha de acessibilidade mais comum em animação, e a mais fácil de corrigir.
Quando vale trazer uma biblioteca
A maior parte do acervo é CSS puro — e isso é uma escolha, não uma limitação. Código sem dependência você cola em qualquer projeto e funciona.
Biblioteca ganha o lugar dela quando resolve algo que folha de estilo não faz:
- Cascata calculada. Em CSS, o atraso de cada item de uma lista é escrito à mão — e quebra quando a lista muda de tamanho. Com stagger, o atraso é calculado.
- Interpolar texto. CSS anima propriedade, não conteúdo. Um número que conta de zero até o total precisa de JavaScript de qualquer jeito.
- Encadear etapas. Sequências com dependência entre passos são difíceis de manter em
@keyframes. - Controlar progresso. Pausar, inverter, reagir a rolagem ou a arrastar.
Fora desses casos, o CSS ganha em peso e em portabilidade. Fade, escala, rotação e mudança de estado não precisam de biblioteca — e trazer uma para resolver um transition de três linhas é adicionar dependência sem receber nada em troca.
Perguntas frequentes
- Posso usar estas animações em projeto comercial?
- Pode. São criações originais do Devs & IA, liberadas para uso pessoal e comercial, com ou sem alteração, sem necessidade de crédito. As peças marcadas como anime.js usam essa biblioteca, que é MIT — nesse caso, quem se aplica é a licença dela, também permissiva.
- Preciso instalar alguma coisa?
- Na maioria das peças, não: são HTML e CSS puro. Cole o HTML onde o elemento deve aparecer e o CSS na sua folha de estilo. Só as peças marcadas como anime.js exigem instalar a biblioteca — e o filtro 'Só CSS puro' esconde justamente essas, se você quiser evitar dependência.
- Qual a diferença entre transition e animation?
- transition anima a mudança entre dois estados e precisa de um gatilho, como hover ou uma classe adicionada por JavaScript. animation com @keyframes roda sozinha, pode ter várias etapas e repetir indefinidamente. Regra prática: se o movimento responde a uma ação, use transition; se acontece por conta própria, use animation.
- Por que minha animação está travando no celular?
- Quase sempre porque a propriedade animada obriga o navegador a recalcular o layout a cada quadro — width, height, top, left, margin. Troque por transform e opacity, que são resolvidas na etapa final de composição. O segundo motivo mais comum é quantidade: uma peça animada é barata, quarenta na mesma tela não são.
- Como faço a animação rodar só quando o elemento aparece na tela?
- Com IntersectionObserver, que avisa quando o elemento entra na área visível — aí você adiciona a classe que dispara a animação. É melhor que animar tudo no carregamento por dois motivos: o navegador não gasta trabalho com o que ninguém está vendo, e a pessoa não perde a animação de um bloco que estava fora da tela.
- Preciso mesmo me preocupar com prefers-reduced-motion?
- Sim. Existe gente que sente náusea e tontura com movimento na tela, e o sistema operacional já expõe essa preferência — respeitá-la é uma media query. A regra: desligue o que é decorativo e reduza, sem remover, o que comunica estado. Um spinner precisa continuar indicando que algo está carregando, só mais devagar.
Todas as animações desta página são criações originais do Devs & IA, livres para usar e adaptar em projetos pessoais e comerciais. As peças marcadas como anime.js usam a biblioteca anime.js (MIT, de Julian Garnier) — o código da animação é nosso, a biblioteca é dela.