CSS Animations: La Base de Todo
CSS es la herramienta más eficiente para la mayoría de las animaciones en interfaces web. Las transiciones y keyframes CSS son nativas del navegador, no requieren dependencias adicionales y tienen excelente rendimiento. Aprende a usarlas correctamente antes de recurrir a librerías JavaScript.
Transitions vs Keyframes: cuándo usar cada uno
- Transitions: para cambios de estado entre dos valores (hover on/off, visible/oculto) — la mayoría de los casos
- Keyframes: para animaciones con múltiples pasos o que se repiten (loading, pulsing, bouncing)
- Transitions son más simples: solo defines la propiedad, duración y easing — el navegador interpola
- Keyframes dan más control: defines los fotogramas clave (0%, 50%, 100%) y qué pasa en cada uno
- Combina ambos: transitions para interacciones del usuario, keyframes para animaciones de estado
Propiedades seguras para animar (composited)
- transform: translate, scale, rotate — movimiento, tamaño y rotación sin afectar al layout
- opacity: transparencia — combinado con transform cubre el 90% de las animaciones UI
- filter: blur, brightness, saturate — para efectos visuales (puede ser más pesado en dispositivos viejos)
- EVITAR animar: width, height, padding, margin, top, left, font-size — causan reflow y son lentas
- La regla: si solo cambias transform y opacity, tu animación correrá a 60fps sin problemas
Patrones CSS comunes
- Fade in: opacity de 0 a 1 con transition o keyframe — la transición más usada
- Slide up: transform: translateY(20px) → translateY(0) con opacity — elegante para elementos que aparecen
- Scale: transform: scale(0.95) → scale(1) — sutil crecimiento para cards y modales
- Stagger con animation-delay: cada hijo con un delay incrementado (child:nth-child(1) 0ms, (2) 50ms, (3) 100ms...)
- Exit animations: usa la misma transición en reversa o fadeOut para mantener coherencia
Performance y buenas prácticas
- Usa will-change: transform en elementos que animarás frecuentemente — promueve a GPU layer
- No abuses de will-change: cada elemento con will-change consume memoria de GPU — úsalo solo donde es necesario
- Testa en dispositivos reales: una animación fluida en tu MacBook puede ser laggy en un Android de gama media
- Chrome DevTools → Performance panel: graba tu animación y verifica que mantiene 60fps
- Siempre incluye prefers-reduced-motion: el respeto por la accesibilidad no es opcional
Ejemplo práctico
/* Fade in + slide up al entrar al viewport */
.card {
opacity: 0;
transform: translateY(24px);
transition: opacity 400ms ease, transform 400ms ease;
}
.card.visible {
opacity: 1;
transform: translateY(0);
}
/* Stagger para listas */
.list-item {
opacity: 0;
transform: translateY(16px);
animation: fadeSlideUp 400ms ease forwards;
}
.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }
@keyframes fadeSlideUp {
to {
opacity: 1;
transform: translateY(0);
}
}
Consejo: El Intersection Observer API es tu mejor amigo para trigger animaciones cuando los elementos entran al viewport. Es nativo del navegador y mucho más eficiente que escuchar el evento scroll.