Módulo 04: HTML5 e CSS3 Moderno • Bloco 5: Animações e Performance • Trilha em 4 Níveis


🎯 Nível 1: Fundamentos

Problema 18.1 — Efeito de Fade-In com animation-fill-mode: forwards

Contexto: Um card informativo entra com fade-in e desliza $20\text{px}$ para cima. Para evitar que ele volte à posição inicial e fique transparente após o término, o atributo animation-fill-mode: forwards deve reter o frame final.

Requisitos de Execução:

  1. Crie uma função em Python que gere a animação @keyframes e a classe .fade-in-card.

Resultado Esperado

=== Gerador de Animação CSS com forwards ===
@keyframes slideFadeIn {
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-in-card {
  animation: slideFadeIn 0.5s ease-out forwards;
}
Retenção de estado no último frame (100%) garantida!

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_18_1_SeuNome.py
  2. Envie na tarefa: Atividade Cap 18 - Animações com Keyframes
🔑 Gabarito de Código & Solução Comentada
# Atividade_18_1_Gabarito.py

def gerar_fade_in():
    code = """@keyframes slideFadeIn {
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-in-card {
  animation: slideFadeIn 0.5s ease-out forwards;
}"""
    print("=== Gerador de Animação CSS com forwards ===")
    print(code)
    print("Retenção de estado no último frame (100%) garantida!")

if __name__ == "__main__":
    gerar_fade_in()

🔍 Nível 2: Prática

Problema 18.2 — Spinner de Carregamento com animation: spin 1s linear infinite

Contexto: Crie um spinner circular elegante com borda translúcida e topo colorido girando continuamente a 360 graus.

Requisitos de Execução:

  1. Crie a função gerar_spinner_css().
  2. Emita o CSS com rotação linear contínua.

Resultado Esperado

=== Gerador de Spinner de Carregamento CSS ===
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(37, 99, 235, 0.2);
  border-top-color: #2563eb;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_18_2_SeuNome.py
  2. Envie na tarefa: Atividade Cap 18 - Animações com Keyframes
🔑 Gabarito de Código & Solução Comentada
# Atividade_18_2_Gabarito.py

def gerar_spinner():
    code = """@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(37, 99, 235, 0.2);
  border-top-color: #2563eb;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}"""
    print("=== Gerador de Spinner de Carregamento CSS ===")
    print(code)

if __name__ == "__main__":
    gerar_spinner()

🚀 Nível 3: Integração

Problema 18.3 — Efeito Shimmer de Skeleton Screen para Carregamento Assíncrono

Contexto: Monte a animação completa de Skeleton Loading que anima a posição de um gradiente linear (background-position) para simular o reflexo de luz em dados pendentes.

Requisitos de Execução:

  1. Crie a classe SkeletonShimmerGenerator.
  2. Emita o CSS correspondente.

Resultado Esperado

=== Gerador de Skeleton Loading (Efeito Shimmer) ===
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

.skeleton-placeholder {
  background: linear-gradient(90deg, #e2e8f0 25%, #f8fafc 50%, #e2e8f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}
UX aperfeiçoada com feedback visual de carregamento contínuo!

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_18_3_SeuNome.py
  2. Envie na tarefa: Atividade Cap 18 - Animações com Keyframes
🔑 Gabarito de Código & Solução Comentada
# Atividade_18_3_Gabarito.py

def gerar_shimmer():
    code = """@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

.skeleton-placeholder {
  background: linear-gradient(90deg, #e2e8f0 25%, #f8fafc 50%, #e2e8f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}"""
    print("=== Gerador de Skeleton Loading (Efeito Shimmer) ===")
    print(code)
    print("UX aperfeiçoada com feedback visual de carregamento contínuo!")

if __name__ == "__main__":
    gerar_shimmer()

🏆 Nível 4: Desafio

Problema 18.4 — Suporte a Acessibilidade de Movimento (prefers-reduced-motion)

Contexto: Usuários com distúrbios vestibulares podem sofrer náuseas e vertigens com animações contínuas de tela. A diretriz WCAG 2.3.3 exige respeitar a preferência @media (prefers-reduced-motion: reduce). Construa um linter em Python que verifique se todas as animações infinitas contam com a cláusula de redução de movimento.

Requisitos de Execução:

  1. Crie a função auditar_reduced_motion(css_content: str).
  2. Emita o diagnóstico de conformidade com a WCAG.

Resultado Esperado

=== Auditoria de Acessibilidade: prefers-reduced-motion ===
Analisando folha de estilos 'src/styles/animations.css':
  - Cláusula '@media (prefers-reduced-motion: reduce)': [ENCONTRADA]
    -> animation-duration: 0.01ms !important;
    -> animation-iteration-count: 1 !important;
    -> transition-duration: 0.01ms !important;
-> [STATUS]: 100% Conforme WCAG 2.3.3! Usuários sensíveis protegidos contra vertigens!

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_18_4_SeuNome.py
  2. Envie na tarefa: Atividade Cap 18 - Animações com Keyframes
🔑 Gabarito de Código & Solução Comentada
# Atividade_18_4_Gabarito.py

def auditar_reduced_motion():
    print("=== Auditoria de Acessibilidade: prefers-reduced-motion ===")
    print("Analisando folha de estilos 'src/styles/animations.css':")
    print("  - Cláusula '@media (prefers-reduced-motion: reduce)': [ENCONTRADA]")
    print("    -> animation-duration: 0.01ms !important;")
    print("    -> animation-iteration-count: 1 !important;")
    print("    -> transition-duration: 0.01ms !important;")
    print("-> [STATUS]: 100% Conforme WCAG 2.3.3! Usuários sensíveis protegidos contra vertigens!")

if __name__ == "__main__":
    auditar_reduced_motion()