Hay una prueba simple para saber si una animación merece existir. Quitala y preguntate si alguien se perdería.
Si la respuesta es "se vería más seco pero se entiende igual", esa animación es decoración. No está mal tener decoración —no todo tiene que ser funcional— pero conviene saber cuál es cuál, porque la decoración se paga en milisegundos y la función se cobra en comprensión.
Para qué sirve realmente el movimiento
El movimiento en una interfaz hace tres trabajos, y nada más:
Explica el origen. Un modal que aparece desde el botón que lo abrió le dice al usuario de dónde salió y a dónde va a volver. Uno que aparece con un fundido desde el centro no le dice nada.
Mantiene la continuidad. Cuando una lista se reordena, ver los elementos moverse a su nueva posición preserva el modelo mental. Si simplemente se redibujan, el usuario pierde de vista el ítem que estaba siguiendo y tiene que volver a buscarlo.
Comunica estado. Un botón que responde al hover confirma que es interactivo antes de que lo toques. Un spinner dice "seguimos acá". Un borde que se pone rojo dice "esto está mal" más rápido que cualquier texto.
Todo lo demás es adorno.
Los números que importan
Después de bastantes iteraciones, estos son los rangos con los que trabajo:
| Tipo | Duración | Por qué |
|---|---|---|
| Hover, focus | 120–180ms | Tiene que sentirse instantáneo pero no brusco |
| Entrada de elemento | 300–450ms | Suficiente para seguirlo con la vista |
| Transición de página | 250–350ms | Más que esto y se siente lento |
| Ambiente (loops) | 6–20s | Tan lento que no compite por atención |
La curva importa tanto como la duración. Casi todo lo que entra debería usar una curva que desacelera al final —algo tipo cubic-bezier(0.22, 1, 0.36, 1)— porque imita cómo se mueven las cosas con masa. linear solo sirve para rotaciones continuas y barras de progreso.
El costo que nadie mide
Acá viene la parte técnica que importa.
El navegador puede animar cuatro propiedades sin recalcular el layout: transform, opacity, filter y backdrop-filter. Todo lo demás —width, height, top, margin, padding— obliga a recalcular posiciones, y en una lista de treinta elementos eso se nota.
/* Caro: recalcula layout en cada frame */
.card:hover { margin-top: -4px; }
/* Barato: se compone en la GPU */
.card:hover { transform: translateY(-4px); }
La diferencia en una laptop moderna es invisible. En un teléfono de gama media con quince pestañas abiertas, es la diferencia entre fluido y entrecortado.
El caso de las animaciones ambiente
Las animaciones que corren todo el tiempo —una esfera que rota, un gradiente que respira— tienen un costo distinto: no es un pico, es un impuesto constante sobre la batería.
Mi regla: si es puro CSS sobre transform u opacity, el compositor se encarga y el hilo principal queda libre. Si necesita JavaScript por frame, probablemente no vale la pena. Un requestAnimationFrame que corre indefinidamente mientras el usuario lee un artículo es una decisión que hay que justificar.
Lo que no es negociable
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Esto no es una cortesía. Para gente con trastornos vestibulares, el movimiento en pantalla produce mareo y náusea reales. El sistema operativo ya tiene la preferencia configurada; lo único que hay que hacer es respetarla.
Y respetarla no significa apagar todo. Significa reemplazar el movimiento por un cambio de opacidad, que comunica lo mismo sin desplazar nada.
El error más común
Animar la entrada de contenido que ya estaba ahí.
Cuando una página carga y todos los bloques hacen fade-in secuencial, el usuario que venía a leer algo específico tiene que esperar a que la interfaz termine de presentarse. Es la versión web de alguien que carraspea antes de cada frase.
La animación de entrada tiene sentido cuando el contenido aparece —al hacer scroll hacia una sección nueva, al abrirse un panel, al llegar un dato— no cuando ya estaba en el HTML que el servidor mandó.
Una interfaz bien animada no se nota. Se nota cuando falta, porque de repente no entendés de dónde salió esa cosa.
Resumen
- Si quitarla no confunde a nadie, es decoración. Está bien, pero medí lo que cuesta.
transformyopacity. El resto, pensalo dos veces.- Curvas que desaceleran para entradas,
linearsolo para loops. prefers-reduced-motionsiempre.- No animes lo que ya estaba.
