Menu

Animação CSS: @keyframes, propriedades e exemplos

As animações CSS levam um elemento pelas etapas que você define em @keyframes, sozinhas e quantas vezes você quiser. Veja a sintaxe do @keyframes, as oito propriedades de animation, fill-mode e direction, indicadores de carregamento, como pausar e como respeitar o movimento reduzido.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Uma animação CSS em um exemplo

Uma animação tem duas partes: o @keyframes, que descreve as etapas, e a propriedade animation, que as aplica a um elemento com uma duração. Este card desliza e aparece aos poucos quando a página carrega:

Edite o código (ou mude a duração para 2s) e a prévia recarrega, para você ver o card entrar de novo. O bloco @media (prefers-reduced-motion: reduce) troca os keyframes por um fade simples só para leitores cujo sistema está configurado para reduzir movimento.

Sintaxe do @keyframes

@keyframes pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
  • from é o mesmo que 0% e to é o mesmo que 100%.
  • Acrescente quantas etapas em porcentagem precisar. Etapas com os mesmos estilos podem dividir uma linha: 0%, 100% { ... }.
  • Uma propriedade que falta no primeiro ou no último keyframe é animada a partir do valor do próprio elemento, ou até ele.
  • O nome (pulse) é o que você passa para animation-name. Ele diferencia maiúsculas de minúsculas e não pode ser uma palavra-chave como none.

As propriedades de animation

PropriedadeO que definePadrão
animation-namequal @keyframes rodarnone
animation-durationduração de um ciclo0s
animation-timing-functioncurva de velocidade entre os keyframesease
animation-delayespera antes do primeiro ciclo (negativo começa no meio)0s
animation-iteration-countnúmero de ciclos, ou infinite1
animation-directionnormal, reverse, alternate, alternate-reversenormal
animation-fill-modeestilos antes e depois: none, forwards, backwards, bothnone
animation-play-staterunning ou pausedrunning

O shorthand as aceita em quase qualquer ordem. A única regra é que o primeiro valor de tempo é a duração e o segundo é o delay:

.loader {
  animation: pulse 1.2s ease-in-out 0.2s infinite alternate both;
  /*         name  duration timing  delay count   direction fill */
}

direction e fill-mode, ao vivo

Escolha uma direção, um fill mode e uma contagem e aperte Play. A caixa percorre 200px até o fim da trilha. O painel diz onde ela ficou depois que a animação terminou:

O que observar:

  • fill-mode: none (o padrão): depois do último quadro, a caixa volta de uma vez para x = 0 e fica âmbar de novo.
  • forwards: ela fica no último keyframe. Com normal, isso é x = 200 e verde; com reverse, ela termina em x = 0 e azul, porque o último keyframe tocado foi o from.
  • alternate com contagem 2 vai e volta, então até com forwards termina em x = 0.

Loops infinitos: um indicador de carregamento

infinite repete para sempre, e um animation-delay em cada filho os desencontra para se moverem em sequência. Mantenha os loops calmos: lentos, pequenos, sem piscar.

role="status" com um aria-label avisa a quem usa leitor de tela que algo está carregando, o que os pontos sozinhos não dizem. Para um círculo girando, veja a página de rotate.

Pausar e controlar animações

animation-play-state: paused congela uma animação onde ela está, e running continua dali. Passe o mouse sobre a barra abaixo para pausá-la:

Pelo JavaScript, element.getAnimations() devolve as animações CSS em andamento, cada uma com pause(), play(), cancel() e um currentTime que você pode ler ou definir. O evento animationend dispara quando uma animação não infinita termina, e animationiteration no fim de cada ciclo.

Respeite o movimento reduzido e nunca pisque

Duas regras de acessibilidade valem para toda animação:

  1. Movimento reduzido. As pessoas podem pedir ao sistema menos movimento porque o movimento lhes faz mal. O padrão mais seguro é só acrescentar movimento quando elas não pediram menos:
@media (prefers-reduced-motion: no-preference) {
  .hero-title { animation: slide-in 0.8s ease-out both; }
}
  1. Nada de piscar. Conteúdo que pisca mais de três vezes em um segundo pode provocar convulsões. Evite de vez piscadas rápidas e de alto contraste.

Mantenha as animações suaves

Anime transform e opacity sempre que puder. O navegador consegue aplicá-las sem montar a página de novo, então elas continuam suaves até em celulares lentos. Animar width, height, top, left ou margin recalcula o layout a cada quadro. Para mover um elemento, use translate(), da página do transform.

Erros comuns

  • Sem duração. animation: fade; não faz nada, porque a duração padrão é 0s.
  • Um nome que não bate. O animation-name precisa ser exatamente igual ao nome do @keyframes, incluindo maiúsculas e minúsculas.
  • Voltar de uma vez no fim. Acrescente forwards (ou both) para manter o último keyframe.
  • Um piscar antes de uma animação com delay começar. Durante o animation-delay, o elemento mostra os estilos normais. backwards (ou both) aplica o primeiro keyframe durante o delay.
  • Reiniciar uma animação definindo o mesmo valor. Definir o mesmo animation de novo não faz nada. Remova, force um reflow (el.offsetWidth) e defina de novo, como faz o botão Play acima.
  • Animar o display. Ele troca de uma vez. Anime opacity e transform.

Perguntas frequentes

Como fazer uma animação no CSS?

Defina as etapas com @keyframes name { from { ... } to { ... } } e aplique ao elemento com a propriedade animation e uma duração: animation: name 1s ease-out;. A duração é obrigatória, porque o padrão dela é 0s.

O que animation-fill-mode: forwards faz?

Mantém os estilos do último keyframe depois que a animação termina. Sem ele, o elemento volta de uma vez aos estilos normais. backwards aplica o primeiro keyframe durante o delay, e both faz os dois.

Como fazer uma animação CSS em loop infinito?

Defina animation-iteration-count: infinite ou acrescente infinite ao shorthand: animation: spin 1s linear infinite;. Acrescente alternate para tocar para frente e depois para trás a cada ciclo.

Qual a diferença entre animation e transition no CSS?

Uma transition anima uma propriedade entre dois valores quando ela muda, normalmente no hover ou na troca de uma classe. Uma animation roda sozinha assim que é aplicada, pode ter qualquer número de keyframes e pode se repetir, inverter e pausar.

Como pausar uma animação CSS?

Defina animation-play-state: paused no elemento, por exemplo no :hover ou por uma classe acrescentada pelo JavaScript. Voltar para running continua de onde parou.

Como desligar animações para quem prefere movimento reduzido?

Envolva a animação em @media (prefers-reduced-motion: no-preference) { ... } ou remova-a dentro de @media (prefers-reduced-motion: reduce) { ... }. A query segue a configuração de reduzir movimento do sistema operacional do usuário.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR