Qué son los keyframes
Los @keyframes en CSS son la manera estándar de definir animaciones complejas. A diferencia de transition, que sólo interpola entre dos estados, keyframes te deja definir múltiples puntos intermedios y darle un nombre a la animación para reutilizarla.
Sintaxis básica
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.elemento {
animation: fadeIn 0.5s ease-in-out;
} Podés usar from/to o porcentajes (0%, 50%, 100%). Los porcentajes te dan control fino sobre puntos intermedios.
Animaciones que valen la pena
- fadeIn: entrada suave para elementos nuevos.
- slideUp / slideDown: revelado desde arriba o abajo.
- bounce: rebote elástico, útil para llamar atención.
- pulse: latido para indicar acción o estado.
- spin: rotación continua, clásica para loaders.
- shake: sacudida horizontal para señalar error.
Performance: animá lo que el GPU puede componer
Los navegadores tienen tres etapas de rendering: layout, paint y composite. Animar propiedades que requieren layout (width, height, top, left) recalcula posiciones y es lento. Animar opacity y transform sólo toca la etapa de composite, que corre en GPU. Diferencia: 60fps vs jank.
- Sí: opacity, transform (translate, scale, rotate).
- Cuidado: filter, color (paint).
- Evitar: width, height, padding, top, left (layout).
Easing
El easing es la curva de aceleración de la animación. linear se siente mecánico. ease-in-out es el default agradable. cubic-bezier() te deja diseñar curvas custom: para movimiento "natural" probá cubic-bezier(0.2, 0.8, 0.2, 1), popular en sistemas de diseño como Material y iOS.
Animation shorthand
animation: name duration timing-function delay iteration-count direction fill-mode; Ejemplo completo: animation: fadeIn 0.5s ease-in-out 0.2s 1 normal both;. fill-mode: both mantiene el estado final para que no haya "pop" al terminar.
Accesibilidad
Respetá la preferencia prefers-reduced-motion. Algunas personas tienen vértigo o problemas vestibulares con animaciones. Envolvé tus animaciones en una media query así:
@media (prefers-reduced-motion: no-preference) {
.elemento { animation: fadeIn 0.5s; }
}