Ficha 01 · Animação CSS e performance
- Conceitos de animação web
- Escrever CSS
- Optimizar performance
Parte I · Verdadeiro ou Falso (30 pts)
Indica V ou F e justifica.
- Animar
transformeopacityé geralmente mais performante do que animarwidtheleft. (5 pts) - O
requestAnimationFrameé menos suave que osetIntervalpara animações. (5 pts) - O Intersection Observer permite detectar quando um elemento entra no viewport sem ouvir o evento
scrollcontinuamente. (5 pts) - O media query
prefers-reduced-motionserve para respeitar utilizadores que preferem menos animação. (5 pts) - Uma
transitionem CSS é adequada para animar a mudança entre dois estados (ex: hover). (5 pts) - O GSAP só funciona com a propriedade
transform. (5 pts)
- V —
transform/opacitycorrem no compositor (GPU), sem reflow;width/leftprovocam reflow/repaint, mais caros. - F — É o contrário: o
requestAnimationFramesincroniza com o refresh do ecrã (~60 fps), sendo mais suave e eficiente quesetInterval. - V — O Intersection Observer notifica de forma eficiente sem ouvir
scrollconstantemente. - V — Respeita a preferência de acessibilidade de reduzir movimento (evita náuseas/desconforto).
- V — As transitions são ideais para animar entre dois estados (default ↔ hover/focus).
- F — O GSAP anima praticamente qualquer propriedade numérica (cor, opacidade, posição, etc.), não só transform.
Parte II · Escrever CSS para uma animação (35 pts)
Implementa as seguintes animações em CSS.
Exercício 1 · Botão com hover (15 pts)
Cria um botão .cta que, ao passar o rato, sobe ligeiramente (2 px), escurece o fundo e mostra uma sombra, tudo com transição suave.
.cta {
background: #4F46E5;
color: #fff;
padding: 12px 24px;
border: none;
border-radius: 8px;
transform: translateY(0);
box-shadow: 0 2px 6px rgba(0,0,0,.15);
transition: transform .2s ease, background .3s ease, box-shadow .3s ease;
cursor: pointer;
}
.cta:hover {
background: #4338CA;
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0,0,0,.25);
}
(Avaliar: uso de transition nas propriedades certas, translateY no hover, escurecer + sombra.)
Exercício 2 · Loader com keyframes (20 pts)
Cria um spinner circular .loader que roda continuamente (360°), usando @keyframes.
.loader {
width: 40px;
height: 40px;
border: 4px solid #e5e7eb; /* anel claro */
border-top-color: #4F46E5; /* segmento colorido */
border-radius: 50%;
animation: rodar 0.8s linear infinite;
}
@keyframes rodar {
to { transform: rotate(360deg); }
}
/* Acessibilidade */
@media (prefers-reduced-motion: reduce) {
.loader { animation-duration: 1.5s; }
}
(Avaliar: @keyframes com rotate, animation infinite, círculo correcto; bónus por considerar reduced-motion.)
Parte III · Corrigir animação com problemas de performance (35 pts)
O código seguinte anima um card a deslizar e crescer, mas está "aos saltos" (não chega a 60 fps). Identifica os problemas de performance e reescreve o CSS de forma performante.
.card {
position: absolute;
left: 0;
width: 200px;
height: 120px;
transition: left 0.4s, width 0.4s, height 0.4s;
}
.card.activo {
left: 300px;
width: 260px;
height: 160px;
}
Problemas identificados (15 pts)
- Anima left, width e height → cada uma provoca reflow/repaint em todos os frames, o que é caro e causa "saltos".
- Estas propriedades não correm na GPU/compositor.
Solução: usar transform (20 pts)
.card {
position: absolute;
left: 0;
width: 200px;
height: 120px;
transform: translateX(0) scale(1);
transform-origin: left top;
transition: transform 0.4s ease;
will-change: transform; /* enquanto anima */
}
.card.activo {
/* deslocar 300px e crescer ~1.3x via scale */
transform: translateX(300px) scale(1.3);
}
Explicação:
- translateX substitui a animação de left.
- scale substitui a animação de width/height (crescimento proporcional).
- Apenas transform é animado → corre no compositor, atingindo 60 fps.
- will-change: transform prepara a optimização (idealmente só durante a animação).
(Aceita-se nota de que o scale altera proporção; se for preciso manter dimensões exactas sem distorção, comentar o trade-off. O essencial é trocar left/width/height por transform.)