Pular para o conteúdo
charmotion

Como adicionar animação a um site (HTML, CSS, JS)

Por equipe Charmotion · Atualizado em

Ilustração de capa do guia: Como adicionar animação a um site (HTML, CSS, JS), com personagens de demonstração do Charmotion

Para adicionar animação a um site, use transições CSS e @keyframes para o movimento da interface, a Web Animations API quando o JavaScript precisa controlar a reprodução, um <video> sem som com reprodução automática para clipes e um player Lottie ou Rive para ilustrações e personagens. Anime transform e opacity e respeite prefers-reduced-motion.

Principais pontos

  • O CSS cobre a maior parte do movimento da interface; envolva ou desative as animações em @media (prefers-reduced-motion: reduce).
  • element.animate() retorna um objeto Animation que você pode pausar, inverter e aguardar com await.
  • O vídeo só toca automaticamente quando está sem som; no iPhone, também é preciso playsinline.
  • Vídeo com fundo transparente exige dois arquivos: primeiro um .mov HEVC com alfa para o Safari, depois um WebM VP9 com alfa para os demais navegadores.
  • Para um personagem que reage a eventos, uma state machine do Rive é um único arquivo pequeno, em vez de um vídeo por estado.

Já tem um personagem ou logo? Veja seu personagem em telas reais de app: telas de splash, onboarding, carregamento e estado vazio. É grátis, roda no navegador e não envia nada.

Usar CSS, JavaScript ou um arquivo de animação?

Escolha pela tarefa, não pela ferramenta. Cada opção tem seu lugar:

TrabalhoMelhor opção
Estados de hover, menus, fades, feedback de botõesTransições CSS e @keyframes
Movimento que você inicia, pausa ou encadeia pelo códigoWeb Animations API (element.animate())
Um clipe de marketing ou demo de produto<video> (MP4, WebM)
Uma ilustração ou sequência de ícones criada por um designerLottie ou dotLottie
Um mascote que muda de estado conforme eventosState machine do Rive
Tabela de decisão: APIs nativas para feedback de interface, efeitos de ícone para ícones, uma state machine do Rive para personagens, vídeo para clipes de marketing
Escolha o método de animação conforme a tarefa.

CSS e a Web Animations API não custam nada para carregar, porque já vêm no navegador. Vídeo, Lottie e Rive acrescentam um arquivo cada e, no caso de Lottie e Rive, um script de player. Esse custo compensa quando o movimento foi desenhado por um designer, e não descrito em código. Se você só precisa de um spinner ou de um fade, fique no CSS.

Como funcionam as transições CSS e os @keyframes?

Uma transição anima uma propriedade entre dois valores quando ela muda, por exemplo em :hover. Uma animação com keyframes define etapas nomeadas com @keyframes e as aplica com o atalho animation, podendo rodar ao carregar, em loop ou uma única vez.

.badge {
  animation: pop-in 400ms ease-out both;
}

@keyframes pop-in {
  from { opacity: 0; transform: scale(0.8); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .badge { animation: none; }
}

O fill mode both mantém o primeiro frame aplicado antes de a animação começar e o último depois que ela termina, o que evita um flash do estado sem estilo.

A media feature prefers-reduced-motion informa se o visitante ativou a opção de reduzir movimento no iOS, macOS, Windows ou Android. Ela tem dois valores, no-preference e reduce, e o MDN a classifica como amplamente disponível desde janeiro de 2020. Remover movimentos grandes em reduce é o mínimo; um fade curto de opacidade geralmente continua aceitável. O guia de movimento reduzido explica o que manter e o que remover.

Quando a Web Animations API é melhor que CSS?

Use a Web Animations API quando a animação depende de dados em tempo de execução ou quando você precisa controlá-la depois que ela começa. element.animate(keyframes, options) recebe os mesmos keyframes do CSS, escritos como objetos JavaScript, e retorna um objeto Animation.

const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
const card = document.querySelector(".card");

if (!reduce) {
  const anim = card.animate(
    [
      { transform: "translateY(0)" },
      { transform: "translateY(-8px)" },
      { transform: "translateY(0)" },
    ],
    { duration: 600, easing: "ease-out", iterations: 1 }
  );
  anim.finished.then(() => card.classList.add("settled"));
}

O objeto retornado tem play(), pause(), reverse() e cancel(), além de uma promise finished. Isso facilita encadear etapas, navegar pela animação com currentTime ou interrompê-la quando o usuário sai da página. O CSS não faz nada disso sem alternar classes e escutar animationend.

Media queries não se aplicam a scripts, então verifique prefers-reduced-motion você mesmo com matchMedia, como acima.

Como tocar uma animação em vídeo automaticamente e sem som?

Adicione autoplay muted loop playsinline ao elemento de vídeo. Os navegadores só permitem reprodução automática quando o vídeo está sem som ou não tem faixa de áudio. No iPhone, o WebKit só reproduz vídeo dentro da página com playsinline; sem ele, o vídeo espera um toque e abre em tela cheia.

Para um personagem ou logo sobre o fundo da sua página, você precisa de transparência, e nenhum formato é transparente em todos os navegadores. O Safari reproduz WebM, mas descarta o canal alfa, então liste primeiro um .mov HEVC com alfa e depois um WebM VP9 com alfa:

<video autoplay muted loop playsinline preload="metadata"
       width="400" height="400" poster="/mascot-poster.png">
  <!-- Safari: HEVC with alpha must come first -->
  <source src="/mascot.mov" type="video/quicktime; codecs=hvc1.1.6.H120.b0">
  <!-- Chrome, Edge, Firefox: VP9 with alpha -->
  <source src="/mascot.webm" type="video/webm; codecs=vp09.00.41.08">
</video>
Comparação ampliada entre uma borda suave com canal alfa e uma borda serrilhada de GIF de 1 bit sobre um gradiente

Os navegadores escolhem a primeira fonte que conseguem reproduzir. Se o WebM viesse primeiro, o Safari o escolheria e mostraria uma caixa preta. O guia de vídeo com fundo transparente explica como codificar os dois arquivos. Para movimento reduzido, pause o vídeo com reprodução automática via script quando matchMedia("(prefers-reduced-motion: reduce)") corresponder, e mantenha o poster visível.

Como incorporar uma animação Lottie ou dotLottie?

Lottie é uma exportação em JSON de uma animação do After Effects; dotLottie (.lottie) é um pacote compactado que pode conter várias animações, temas e state machines. O projeto dotlottie-web da LottieFiles oferece players para JavaScript puro, React, Vue, Svelte, Solid e um web component. Todos reproduzem arquivos .json e .lottie.

O web component não exige etapa de build, o que o torna a opção mais fácil em uma página estática:

<dotlottie-wc src="/animations/confetti.lottie" autoplay loop
  style="width: 320px; height: 320px"></dotlottie-wc>
<script type="module"
  src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.10.0/dist/dotlottie-wc.js"></script>

Fixe a versão que você testou em vez de @latest, para que uma atualização não altere sua página sem aviso. Com um bundler, instale @lottiefiles/dotlottie-wc e adicione import "@lottiefiles/dotlottie-wc"; no lugar da tag de script. A biblioteca mais antiga lottie-web, da Airbnb, continua funcionando para arquivos .json se você já a usa.

Como incorporar uma animação Rive e mudar seu estado?

Carregue o runtime web do Rive, aponte-o para um canvas e um arquivo .riv e informe o nome da state machine. O Rive recomenda @rive-app/webgl2 para a maioria dos sites; @rive-app/canvas expõe a mesma API e evita o limite de contextos WebGL por página do navegador, caso você mostre muitas animações ao mesmo tempo. Chame resizeDrawingSurfaceToCanvas() em onLoad para que o desenho fique nítido em telas de alta densidade.

<canvas id="mascot" width="400" height="400"
        role="img" aria-label="Animated mascot"></canvas>
<script src="https://unpkg.com/@rive-app/webgl2@2.44.2"></script>
<script>
  const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
  const r = new rive.Rive({
    src: "/mascot.riv",
    canvas: document.getElementById("mascot"),
    stateMachine: "CharacterViewModelMachine",
    autoplay: !reduce,
    autoBind: true,
    onLoad: () => r.resizeDrawingSurfaceToCanvas(),
  });
</script>

Com autoBind: true, o runtime vincula o view model padrão do arquivo, e você muda o estado escrevendo nele. Em um arquivo com um número mood e um trigger success, fica assim:

const vm = () => r.viewModelInstance;

form.addEventListener("submit", () => { vm().number("mood").value = 5; });  // loading
api.onDone = () => { vm().trigger("success").trigger(); vm().number("mood").value = 0; };

Os arquivos .riv do Charmotion são feitos assim: envie um personagem, mascote ou logo e você recebe CharacterViewModelMachine com um número mood de 0 a 9 (idle, happy, wave, thinking, sad, loading, listening, talking, sleeping, attention) e triggers para success, error, yes, no, enter e exit, além do código para web, React e SwiftUI. Arquivos que usam o sistema de inputs mais antigo também funcionam; veja o guia de state machine.

Como manter as animações do site rápidas?

Três hábitos evitam a maioria dos travamentos e carregamentos lentos:

  • Anime transform e opacity. Os navegadores geralmente conseguem compor essas propriedades sem recalcular o layout. Animar width, top ou margin força o recálculo do layout a cada frame.
  • Carregue players e arquivos só quando necessário. O Rive informa que seu WASM WebGL2 tem 648 KB após compressão brotli (janeiro de 2026); o runtime canvas-lite, mais leve, tem cerca de 373 KB em brotli. Carregue-o nas páginas que mostram um personagem, não no site inteiro, e inicie-o quando o canvas entrar na área visível com um IntersectionObserver.
  • Defina o tamanho de todo elemento de mídia. Defina width e height em canvases e vídeos para que a página não se desloque quando eles carregarem, e use preload="metadata" ou "none" para vídeos abaixo da dobra.
new IntersectionObserver(([entry], obs) => {
  if (entry.isIntersecting) { startMascot(); obs.disconnect(); }
}).observe(document.getElementById("mascot"));

Por fim, dê às animações em loop uma forma de desligar. Quem lê uma página longa ao lado de um mascote pulando sem parar vai agradecer por um botão de pausa ou por um loop idle tranquilo.

Como adicionar um personagem animado a uma página web

  1. Escolha o método. Use CSS para o movimento da interface, vídeo para clipes fixos e um arquivo Rive ou Lottie para personagens desenhados.
  2. Adicione os arquivos. Coloque os arquivos .riv, .lottie ou de vídeo na sua pasta estática, com uma imagem de poster para o vídeo.
  3. Adicione a marcação. Adicione um elemento <canvas>, <dotlottie-wc> ou <video autoplay muted loop playsinline> com tamanho definido.
  4. Carregue o player. Inclua o script do player com versão fixa, ou importe o pacote com seu bundler, apenas nas páginas que precisam dele.
  5. Conecte seus eventos. Defina o número de mood ou dispare triggers a partir de handlers de formulário, fetch ou clique.
  6. Respeite o movimento reduzido. Verifique prefers-reduced-motion no CSS e com matchMedia no script, e mostre um frame estático quando a opção estiver ativa.

Perguntas frequentes

Qual é a forma mais fácil de adicionar animação a um site?

CSS. Uma transição em :hover ou uma animação curta com @keyframes não precisa de biblioteca nem de download extra. Passe para a Web Animations API quando precisar controlar a reprodução via JavaScript, e para Lottie, Rive ou vídeo só quando um designer tiver desenhado o movimento.

Por que meu vídeo de fundo não reproduz automaticamente no iPhone?

Provavelmente falta muted ou playsinline. O Safari do iOS só reproduz automaticamente vídeos sem som ou mudos, e só os reproduz inline com playsinline. O Modo de Pouca Energia também pode bloquear a reprodução automática, então sempre defina uma imagem de poster que funcione sozinha.

GIF serve para animação em site?

Normalmente não. GIFs são bem maiores que arquivos MP4 ou WebM equivalentes e só suportam uma cor totalmente transparente, então bordas suaves ficam serrilhadas. Use um vídeo mudo em loop para clipes, e um arquivo Rive ou Lottie para personagens vetoriais e ícones.

Preciso de um framework para usar Rive ou Lottie?

Não. Os dois têm players em JavaScript puro. O runtime web do Rive e o web component do dotLottie podem ser carregados com uma única tag script numa página HTML estática, e ambos também oferecem pacotes npm e wrappers para React se você usa um bundler.

Respostas rápidas deste guia

Fontes

Guias relacionados