⚡ Curso de CSS • Web-ZoneWare

Animações Profissionais com @keyframes no CSS | Web Academy

Lição 44 de 50

Animações Profissionais com @keyframes no CSS | Web Academy

Na lição anterior, você aprendeu que as transições são perfeitas para suavizar a passagem entre dois estados quando o usuário interage com a página. No entanto, muitas interfaces exigem experiências cinematográficas contínuas: indicadores de carregamento que giram sem parar, notificações que entram suavemente na tela assim que o documento abre, ou ilustrações que flutuam em ciclos infinitos de respiração. Para coreografar múltiplos estágios temporais sem depender de ações do mouse, o CSS nos entrega o poderoso motor de @keyframes e a propriedade animation.

1. A Linha do Tempo: Criando Regras com @keyframes

Uma animação em CSS é dividida em duas partes: a linha do tempo (Timeline), declarada com a regra-arroba @keyframes, e a aplicação da animação, configurada no seletor do elemento.

CSS3 20 linhas
/* 1. DEFINIÇÃO DA LINHA DO TEMPO */
@keyframes pulsarBrilho {
  0% {
    transform: scale(1);
    opacity: 0.6;
  }
  50% {
    transform: scale(1.12);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 0.6;
  }
}
 
/* 2. APLICAÇÃO NO ELEMENTO */
.badge-alerta {
  animation: pulsarBrilho 2s ease-in-out infinite;
}

Você pode usar as palavras-chave from (equivalente a 0%) e to (equivalente a 100%) para animações simples, ou declarar quantos marcos percentuais intermediários desejar (0%, 25%, 60%, 100%) para coreografias ricas.

2. As 8 Subpropriedades do animation

A propriedade abreviada animation encapsula 8 controles cirúrgicos:

Propriedade Valores Principais Função na Animação
animation-name Nome da regra @keyframes Conecta o elemento à sua linha do tempo.
animation-duration Tempo (ex.: 1.5s, 400ms) Duração de exatamente 1 ciclo da animação.
animation-timing-function ease, linear, cubic-bezier, steps() Curva de aceleração do movimento.
animation-delay Tempo positivo ou negativo (ex.: -0.5s) Tempo de espera antes do início do primeiro ciclo.
animation-iteration-count Número inteiro ou infinite Quantas vezes a animação repetirá o ciclo.
animation-direction normal, reverse, alternate alternate cria o efeito de ping-pong (vai e volta suavemente).
animation-fill-mode none, forwards, backwards, both Controla como os estilos persistem antes e após a execução.
animation-play-state running, paused Permite pausar ou retomar a animação (ex.: no :hover).

3. animation-fill-mode: O Fim dos Saltos Bruscos

O maior pesadelo dos iniciantes é animar um card surgindo de baixo para cima com fade-in: a animação roda lindamente e, no instante em que chega a 100%, o card desaparece ou salta bruscamente de volta para o estado inicial!

Isso acontece porque, por padrão (animation-fill-mode: none), o navegador descarta todos os estilos do @keyframes assim que a animação termina.

A Solução Definitiva com forwards e both:

  • forwards: Ordena ao navegador que mantenha permanentemente os estilos do último frame (100%) na tela após o término. O elemento nunca mais salta de volta!
  • backwards: Aplica os estilos do primeiro frame (0%) durante o período do animation-delay (evita que o elemento apareça antes da hora).
  • both: O padrão ouro! Aplica tanto forwards quanto backwards, garantindo entradas de tela impecáveis.
CSS3 15 linhas
/* Animação de Entrada Perfeita e Sem Saltos */
.card-entrada {
  animation: deslizarParaCima 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}
 
@keyframes deslizarParaCima {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

4. Pausando Loops no Hover: animation-play-state

Se você tem uma fita de marcas correndo na tela (marquee infinito) ou um disco girando, o usuário pode querer pausar a animação para ler com calma ao passar o mouse:

CSS3 7 linhas
.disco-giratorio {
  animation: girar 8s linear infinite;
}
 
.disco-giratorio:hover {
  animation-play-state: paused; /* Congela o giro exatamente no frame atual! */
}

5. Animações em Degraus com steps(): O Efeito Máquina de Escrever

Em vez de uma transição fluida e suave, a função steps(n) quebra a interpolação em um número fixo de “degraus” discretos. É a base para animar spritesheets de jogos retrô e criar o efeito de digitação mecânica (Typewriter):

CSS3 11 linhas
.texto-maquina {
  overflow: hidden;
  white-space: nowrap;
  width: 22ch; /* Largura exata de 22 caracteres */
  animation: digitar 3s steps(22) infinite alternate;
}
 
@keyframes digitar {
  from { width: 0; }
  to { width: 22ch; }
}

6. Acessibilidade e Performance Gráfica (WCAG 2.2)

Blindagem de Performance e Saúde:

  • Performance: Anime preferencialmente transform e opacity. Evite animar width, height, top ou margin em loops infinitos, sob pena de travar a CPU e descarregar baterias de celulares.
  • Acessibilidade: Elementos piscantes ou que se movem continuamente podem desencadear convulsões ou tonturas severas. É obrigatório incluir:
    CSS3 6 linhas
    @media (prefers-reduced-motion: reduce) {
      * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
      }
    }
    

7. Laboratório Prático: 3 Animações de Produção em Ação

No código interativo abaixo, construímos três animações do mundo real: um Spinner de Carregamento Infinito, um Efeito Máquina de Escrever com Cursor Piscante e um Card com Entrada Suave (Fade & Slide) usando animation-fill-mode: both:

HTML5 113 linhas
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Laboratório de Animações @keyframes CSS</title>
  <style>
    body {
      font-family: 'Inter', system-ui, sans-serif;
      background: #0b0f19;
      color: #f8fafc;
      padding: 40px;
      margin: 0;
    }
 
    .painel-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
      gap: 24px;
      margin-top: 24px;
    }
 
    .card-animacao {
      background: #1e293b;
      border: 1px solid #334155;
      border-radius: 14px;
      padding: 24px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 200px;
      text-align: center;
    }
 
    /* 1. SPINNER DE CARREGAMENTO (LOOP INFINITO) */
    .spinner-radar {
      width: 48px;
      height: 48px;
      border: 4px solid #334155;
      border-top-color: #38bdf8;
      border-radius: 50%;
      animation: girar 1s linear infinite;
    }
 
    @keyframes girar {
      to { transform: rotate(360deg); }
    }
 
    /* 2. EFEITO TYPEWRITER COM STEPS() */
    .typewriter-box {
      display: inline-block;
      font-family: monospace;
      font-size: 1.1rem;
      color: #10b981;
      white-space: nowrap;
      overflow: hidden;
      border-right: 3px solid #10b981;
      width: 17ch; /* 17 caracteres */
      animation: 
        escrever 3.5s steps(17) infinite alternate,
        piscarCursor 0.7s step-end infinite;
    }
 
    @keyframes escrever {
      from { width: 0; }
      to { width: 17ch; }
    }
 
    @keyframes piscarCursor {
      50% { border-color: transparent; }
    }
 
    /* 3. CARD COM ENTRADA CINEMATOGRÁFICA (FILL-MODE: BOTH) */
    .card-entrada-suave {
      animation: surgirComFade 1s cubic-bezier(0.16, 1, 0.3, 1) both;
    }
 
    @keyframes surgirComFade {
      0% {
        opacity: 0;
        transform: translateY(24px) scale(0.95);
      }
      100% {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
    }
  </style>
</head>
<body>
  <h2 style="color:#f1f5f9; margin-top:0;">Animações Avançadas com @keyframes</h2>
  <p style="color:#94a3b8; font-size:0.9rem;">
    Observe três cenários de produção controlados exclusivamente pelo motor gráfico do CSS:
  </p>
 
  <div class="painel-grid">
    <div class="card-animacao">
      <div class="spinner-radar"></div>
      <p style="margin:16px 0 0 0; color:#94a3b8; font-size:0.85rem;">Spinner Infinito (linear infinite)</p>
    </div>
 
    <div class="card-animacao">
      <div class="typewriter-box">Web-ZoneWare 2026</div>
      <p style="margin:16px 0 0 0; color:#94a3b8; font-size:0.85rem;">Typewriter com <code>steps()</code></p>
    </div>
 
    <div class="card-animacao card-entrada-suave">
      <h4 style="margin:0 0 8px 0; color:#38bdf8;">Entrada Blindada</h4>
      <p style="margin:0; font-size:0.85rem; color:#94a3b8;">Retém o estado com <code>animation-fill-mode: both</code></p>
    </div>
  </div>
</body>
</html>

Abra este laboratório no Playground IDE e teste alterar a curva de aceleração ou a direção da animação para alternate para comprovar a versatilidade do @keyframes:

⚡ Abrir no Playground IDE →

8. Resumo e Próximos Passos

  • @keyframes define uma linha do tempo autônoma através de porcentagens (0% a 100%).
  • A propriedade animation conecta o elemento à timeline e dita duração, repetições e velocidade.
  • animation-fill-mode: forwards ou both impede que a animação sofra saltos bruscos ao terminar.
  • animation-direction: alternate cria loops suaves de ida e volta (ping-pong).
  • A função steps() divide a interpolação em degraus rígidos, ideal para sprites e efeitos de digitação.
  • Priorize animar transform e opacity para manter 60fps acelerados pela placa de vídeo.

Próximo Passo: Como organizar paletas de cores globais, alternar entre Modo Claro e Escuro dinamicamente e evitar valores mágicos repetidos no CSS? Na Lição 45, desvendaremos as CSS Variables (Custom Properties) & Dark Mode Dinâmico!

Rolar para cima