Cómo funciona @keyframes en CSS explicado fácil

Las animaciones en CSS pueden parecer un detalle pequeño dentro de una interfaz, pero cuando están bien planteadas ayudan a que una web se sienta más fluida, clara y cuidada. Un botón que aparece suavemente, una tarjeta que entra en pantalla, un loader que gira mientras carga el contenido o un icono que llama la atención sin resultar molesto tienen algo en común: muchas veces están creados con @keyframes en CSS.

La regla @keyframes permite definir una animación paso a paso. Es decir, le indica al navegador cómo debe cambiar un elemento desde un estado inicial hasta un estado final, pasando por todos los puntos intermedios que queramos controlar.

Si ya has trabajado con transiciones o estás empezando a explorar el movimiento en interfaces, este concepto es clave para entender mejor las animaciones CSS y aplicarlas con criterio en tus proyectos.

En este artículo vamos a ver cómo funciona @keyframes en CSS, cuál es su sintaxis, qué propiedades intervienen, cuándo conviene usarlo y qué buenas prácticas deberías tener en cuenta para crear animaciones útiles, accesibles y fáciles de mantener.

Qué es @keyframes en CSS

@keyframes es una regla de CSS que se utiliza para definir los distintos estados de una animación. Su función principal es describir cómo cambia un elemento a lo largo del tiempo.

Dicho de forma sencilla, @keyframes CSS marca los pasos de una animación.

Por ejemplo, podemos hacer que un elemento pase de estar invisible a visible, que se desplace de izquierda a derecha, que cambie de tamaño, que rote, que parpadee o que combine varias transformaciones a la vez.

La estructura básica es esta:

@keyframes nombreAnimacion {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

En este caso, la animación empieza con una opacidad de 0, por lo que el elemento no se ve. Después termina con una opacidad de 1, de modo que aparece completamente visible.

Pero definir el @keyframes no es suficiente. Para que la animación se aplique a un elemento, necesitamos usar la propiedad animation.

.caja {
  animation: nombreAnimacion 1s ease-in-out;
}

Aquí estamos indicando que el elemento con clase .caja debe usar la animación llamada nombreAnimacion, que tendrá una duración de 1s y una curva de movimiento ease-in-out.

Cómo funciona @keyframes paso a paso

Para entender bien las animaciones con keyframes, conviene separar el proceso en dos partes: primero se define la animación y después se aplica al elemento.

1. Definir la animación con @keyframes

La regla @keyframes funciona como una especie de guion. Dentro de ella escribimos qué cambios queremos que ocurran durante la animación.

Podemos usar from y to cuando solo necesitamos indicar un punto inicial y un punto final.

@keyframes aparecer {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

Este ejemplo es muy común para crear un efecto de aparición suave.

También podemos escribirlo con porcentajes:

@keyframes aparecer {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

Ambas versiones hacen lo mismo. from equivale a 0% y to equivale a 100%.

La ventaja de usar porcentajes es que podemos añadir pasos intermedios. Por ejemplo, podemos hacer que un elemento no solo aparezca, sino que también se mueva, crezca o rebote durante el proceso.

2. Aplicar la animación con animation

Una vez definida la animación, necesitamos aplicarla a un selector CSS.

.elemento {
  animation-name: aparecer;
  animation-duration: 1s;
  animation-timing-function: ease;
}

También podemos escribirlo de forma abreviada:

.elemento {
  animation: aparecer 1s ease;
}

La propiedad animation es un shorthand, es decir, una forma resumida de escribir varias propiedades relacionadas con la animación.

Esta separación es importante: @keyframes define qué ocurre, mientras que animation define cómo se ejecuta.

Propiedades principales de CSS animation keyframes

Para trabajar correctamente con CSS animation keyframes, no basta con conocer @keyframes. También es importante entender las propiedades que controlan cómo se reproduce la animación.

animation-name

La propiedad animation-name indica el nombre de la animación que queremos aplicar.

.elemento {
  animation-name: aparecer;
}

Ese nombre debe coincidir con el nombre definido en @keyframes.

@keyframes aparecer {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

Si el nombre no coincide, la animación no funcionará. Este es uno de los errores más habituales cuando se empieza a trabajar con keyframes CSS.

animation-duration

animation-duration define cuánto dura la animación.

.elemento {
  animation-duration: 2s;
}

Puede expresarse en segundos (s) o milisegundos (ms).

.elemento {
  animation-duration: 500ms;
}

Una duración demasiado corta puede pasar desapercibida. Una duración demasiado larga puede resultar pesada. En interfaces web, muchas microinteracciones suelen funcionar bien entre 150ms y 500ms, aunque depende del tipo de efecto y del contexto.

Por ejemplo, no es lo mismo animar el hover de un botón que una entrada de contenido más elaborada. En el primer caso, una duración breve suele ser suficiente. En el segundo, puede tener sentido usar un tiempo algo mayor.

animation-timing-function

La propiedad animation-timing-function controla la velocidad de la animación a lo largo del tiempo.

.elemento {
  animation-timing-function: ease-in-out;
}

Algunos valores frecuentes son:

  • linear: mantiene una velocidad constante.
  • ease: empieza suave, acelera y termina suave.
  • ease-in: empieza lento y acelera.
  • ease-out: empieza rápido y termina lento.
  • ease-in-out: empieza y termina suavemente.

También se puede usar cubic-bezier() para crear una curva personalizada.

.elemento {
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

Este nivel de control es útil cuando queremos que el movimiento tenga una sensación más natural.

animation-delay

animation-delay permite retrasar el inicio de la animación.

.elemento {
  animation-delay: 1s;
}

Esto significa que la animación empezará un segundo después de que se aplique.

Es especialmente útil cuando queremos animar varios elementos de forma escalonada, por ejemplo, una lista de tarjetas que aparece una detrás de otra.

.card:nth-child(1) {
  animation-delay: 0ms;
}

.card:nth-child(2) {
  animation-delay: 120ms;
}

.card:nth-child(3) {
  animation-delay: 240ms;
}

Este recurso puede ayudar a crear una sensación de continuidad, siempre que no se abuse de él.

animation-iteration-count

animation-iteration-count define cuántas veces se repite la animación.

.elemento {
  animation-iteration-count: 3;
}

Si queremos que se repita indefinidamente, usamos infinite.

.loader {
  animation: girar 1s linear infinite;
}

Este valor se utiliza mucho en loaders, iconos animados o efectos decorativos en bucle.

Aun así, conviene usarlo con moderación. Una animación infinita puede ser útil cuando informa de que algo está cargando, pero puede resultar molesta si se utiliza solo como recurso decorativo.

animation-direction

animation-direction indica la dirección en la que se reproduce la animación.

.elemento {
  animation-direction: alternate;
}

Algunos valores posibles son:

  • normal: la animación va de principio a fin.
  • reverse: la animación se reproduce al revés.
  • alternate: alterna entre ida y vuelta.
  • alternate-reverse: alterna, pero empieza al revés.

Esto resulta muy útil para animaciones que deben ir y volver, como un elemento flotando suavemente.

animation-fill-mode

animation-fill-mode controla qué estilos conserva el elemento antes o después de la animación.

.elemento {
  animation-fill-mode: forwards;
}

El valor forwards hace que el elemento conserve el estado final de la animación.

Por ejemplo, si una tarjeta entra desde abajo y termina en su posición normal, forwards permite que se quede en esa posición al terminar.

@keyframes subir {
  from {
    transform: translateY(40px);
    opacity: 0;
  }

  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.tarjeta {
  animation: subir 600ms ease-out forwards;
}

Sin forwards, el elemento podría volver a su estado inicial al finalizar la animación, algo que muchas veces no queremos.

Ejemplo práctico de @keyframes CSS

Veamos un ejemplo completo. Imagina que queremos animar una tarjeta para que aparezca suavemente desde abajo.

<div class="card">
  <h2>Animación con CSS</h2>
  <p>Esta tarjeta aparece con un movimiento suave.</p>
</div>
.card {
  max-width: 320px;
  padding: 24px;
  border-radius: 16px;
  background: #ffffff;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);

  animation: entradaTarjeta 600ms ease-out forwards;
}

@keyframes entradaTarjeta {
  0% {
    opacity: 0;
    transform: translateY(32px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

En este caso, la tarjeta empieza con opacity: 0, por lo que no se ve. Además, tiene transform: translateY(32px), así que aparece ligeramente desplazada hacia abajo.

Al llegar al 100%, la tarjeta ya es visible y vuelve a su posición natural.

Este tipo de animación es muy útil para mejorar la percepción de fluidez en una interfaz. No es una animación decorativa sin sentido: ayuda a que el contenido aparezca de una forma más amable y menos brusca.

Si estás creando interfaces con componentes reutilizables, este mismo enfoque puede combinarse con metodologías de diseño más ordenadas, como explico en el artículo sobre metodologías de desarrollo de software, especialmente cuando trabajas en proyectos donde diseño, desarrollo y experiencia de usuario deben avanzar de forma coordinada.

Usar porcentajes intermedios en @keyframes

Una de las ventajas de @keyframes CSS es que no estamos limitados a un inicio y un final. Podemos añadir tantos puntos intermedios como necesitemos.

@keyframes rebote {
  0% {
    transform: translateY(0);
  }

  30% {
    transform: translateY(-30px);
  }

  60% {
    transform: translateY(10px);
  }

  100% {
    transform: translateY(0);
  }
}

Este ejemplo crea una animación de rebote. El elemento sube, baja un poco y vuelve a su posición original.

.boton {
  animation: rebote 700ms ease-in-out;
}

Los porcentajes intermedios permiten construir animaciones más expresivas. Sin embargo, conviene usarlos con criterio. Cuantos más pasos añadimos, más compleja se vuelve la animación y más fácil es que el resultado parezca exagerado.

Cuándo usar varios pasos

Usar varios porcentajes tiene sentido cuando queremos crear una secuencia clara. Por ejemplo:

  • Un icono que rebota.
  • Un loader con varios estados.
  • Una ilustración que cambia de posición.
  • Un elemento que entra, se agranda y vuelve a su tamaño normal.
  • Un aviso que llama la atención con un pequeño movimiento.

Cuándo evitar demasiados pasos

No siempre hace falta complicar una animación. Si solo queremos suavizar un cambio entre dos estados, puede bastar con una transición o con un @keyframes muy sencillo.

La clave está en hacerse una pregunta antes de añadir movimiento: ¿esta animación ayuda a entender mejor la interfaz o solo añade ruido visual?

Diferencia entre transition y @keyframes

Una duda muy común cuando se empieza a trabajar con animaciones en CSS es cuándo usar transition y cuándo usar @keyframes.

La diferencia principal es esta:

transition suaviza el cambio entre dos estados.
@keyframes permite crear una secuencia de animación con uno o varios pasos.

Por ejemplo, si queremos que un botón cambie de color al pasar el ratón por encima, lo más lógico es usar transition.

.boton {
  background: #753a88;
  transition: background 200ms ease;
}

.boton:hover {
  background: #cc2b5e;
}

Aquí solo hay dos estados: normal y hover. Por eso transition es suficiente.

En cambio, si queremos que un icono pulse constantemente, necesitamos una animación con @keyframes.

.icono {
  animation: pulso 1.5s ease-in-out infinite;
}

@keyframes pulso {
  0% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.12);
  }

  100% {
    transform: scale(1);
  }
}

Aquí no estamos simplemente pasando de un estado a otro por una interacción del usuario. Estamos creando una secuencia que se repite en el tiempo.

Regla rápida para elegir

Una forma sencilla de decidir es esta:

Si hay dos estados, usa transition.
Si hay una secuencia, repetición o control avanzado, usa @keyframes.

Esta regla no cubre todos los casos posibles, pero ayuda mucho cuando estás empezando.

También es útil relacionarlo con el diseño de experiencia de usuario. El movimiento no debería añadirse solo porque “queda bonito”, sino porque ayuda a comunicar mejor una acción o un cambio de estado. Esta idea conecta directamente con temas como el Efecto Patito de Goma aplicado al desarrollo: muchas veces, explicar qué queremos que haga una interfaz nos ayuda a elegir mejor la solución técnica.

Animaciones útiles con keyframes CSS

Las animaciones con keyframes pueden aplicarse a muchos elementos de una web. Lo importante es que tengan una intención clara.

Animación de aparición suave

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.elemento {
  animation: fadeIn 400ms ease forwards;
}

Es una de las animaciones más sencillas y más utilizadas. Sirve para mostrar contenido sin que aparezca de golpe.

Animación de entrada lateral

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-40px);
  }

  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.menu {
  animation: slideIn 500ms ease-out forwards;
}

Puede funcionar bien en menús, paneles, banners o bloques de contenido.

Loader giratorio

.loader {
  width: 40px;
  height: 40px;
  border: 4px solid #eeeeee;
  border-top-color: #cc2b5e;
  border-radius: 50%;
  animation: girar 800ms linear infinite;
}

@keyframes girar {
  to {
    transform: rotate(360deg);
  }
}

Este ejemplo es muy habitual para indicar que una acción está en proceso. La animación es infinita porque el loader debe seguir girando mientras se carga el contenido.

Efecto flotante

@keyframes flotar {
  0% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-12px);
  }

  100% {
    transform: translateY(0);
  }
}

.ilustracion {
  animation: flotar 3s ease-in-out infinite;
}

Este tipo de animación suele usarse en ilustraciones, iconos decorativos o elementos destacados. Debe ser suave para no cansar al usuario.

Buenas prácticas para usar @keyframes en CSS

Las animaciones pueden mejorar mucho una interfaz, pero también pueden empeorarla si se usan sin criterio. Por eso es importante aplicar algunas buenas prácticas.

Usa transform y opacity siempre que puedas

Cuando animes elementos, intenta priorizar propiedades como transform y opacity.

.elemento {
  transform: translateY(20px);
  opacity: 0;
}

Estas propiedades suelen ser más eficientes para el navegador que animar valores como width, height, top, left o margin.

Por ejemplo, en lugar de mover un elemento con top, es preferible usar transform: translate().

@keyframes moverConTop {
  from {
    top: 0;
  }

  to {
    top: 100px;
  }
}

@keyframes moverConTransform {
  from {
    transform: translateY(0);
  }

  to {
    transform: translateY(100px);
  }
}

Esto ayuda a que la animación sea más fluida y tenga mejor rendimiento.

No abuses de las animaciones infinitas

Las animaciones infinitas pueden ser útiles, pero también pueden distraer. Un loader giratorio tiene sentido porque informa al usuario de que algo está cargando. Un icono que no deja de moverse sin motivo puede resultar molesto.

Antes de usar infinite, pregúntate si la animación realmente necesita repetirse todo el tiempo.

.elemento {
  animation-iteration-count: infinite;
}

Si no aporta información o contexto, quizá es mejor evitarlo.

Cuida la accesibilidad

No todas las personas perciben el movimiento de la misma manera. Algunas animaciones pueden causar incomodidad, mareo o dificultad para concentrarse.

Por eso es buena práctica respetar la preferencia del usuario con prefers-reduced-motion.

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms;
    animation-iteration-count: 1;
    scroll-behavior: auto;
  }
}

También puedes desactivar animaciones concretas:

@media (prefers-reduced-motion: reduce) {
  .ilustracion {
    animation: none;
  }
}

Esto demuestra cuidado por la experiencia de todas las personas usuarias.

La accesibilidad no debería tratarse como un extra, sino como parte del propio proceso de diseño y desarrollo. Igual que cuidamos la estructura, los textos o la jerarquía visual, también deberíamos cuidar cómo se comporta el movimiento en pantalla.

Mantén nombres claros

El nombre de una animación debe explicar qué hace.

@keyframes fadeIn {
}

@keyframes slideUp {
}

@keyframes pulse {
}

Evita nombres poco descriptivos como animacion1, movimiento2 o efectoFinal.

En proyectos grandes, una nomenclatura clara ayuda mucho a mantener el CSS ordenado.

Evita animar demasiados elementos a la vez

Una página con muchas animaciones simultáneas puede parecer desordenada y afectar al rendimiento. Además, si todo se mueve, nada destaca.

La animación debe guiar la atención, no competir por ella.

Una buena práctica es reservar las animaciones para momentos concretos:

  • Entrada de contenido importante.
  • Confirmación de una acción.
  • Estados de carga.
  • Feedback visual.
  • Microinteracciones relevantes.

Errores comunes al trabajar con @keyframes CSS

Aunque @keyframes es bastante fácil de entender, hay errores frecuentes que pueden hacer que la animación no funcione como esperamos.

El nombre de la animación no coincide

.caja {
  animation: aparecerCaja 1s ease;
}

@keyframes aparecer {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

En este caso, la animación no se aplicará porque el elemento llama a aparecerCaja, pero el @keyframes se llama aparecer.

La solución es usar exactamente el mismo nombre.

.caja {
  animation: aparecer 1s ease;
}

Falta la duración

.caja {
  animation-name: aparecer;
}

Si no indicamos una duración, la animación no tendrá tiempo para ejecutarse como esperamos. Por eso siempre conviene añadir animation-duration o usar el shorthand completo.

.caja {
  animation: aparecer 1s ease;
}

El elemento vuelve a su estado inicial

Esto ocurre cuando la animación termina y no se conserva el estado final.

.caja {
  animation: subir 500ms ease;
}

Si queremos que el elemento conserve el último estado de la animación, podemos añadir forwards.

.caja {
  animation: subir 500ms ease forwards;
}

Usar animaciones donde bastaría una transición

No todo necesita @keyframes. Si solo quieres suavizar un hover, un cambio de color o una apertura sencilla, probablemente transition sea suficiente.

Usar la herramienta adecuada hace que el CSS sea más limpio y fácil de mantener.

Este mismo criterio también se puede aplicar a otros aspectos del desarrollo frontend. Por ejemplo, cuando eliges entre una solución sencilla o una más compleja en React, conviene pensar primero en el problema que quieres resolver. Si estás en esa fase de aprendizaje, puede ayudarte esta guía sobre cómo aprender React desde cero.

Ejemplo completo: botón con efecto de pulso

Veamos ahora un ejemplo completo de un botón que llama la atención con un pulso suave.

<button class="cta-button">
  Ver proyecto
</button>
.cta-button {
  padding: 14px 24px;
  border: 0;
  border-radius: 999px;
  background: #cc2b5e;
  color: #ffffff;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;

  animation: pulsoSuave 2s ease-in-out infinite;
}

@keyframes pulsoSuave {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(204, 43, 94, 0.35);
  }

  70% {
    transform: scale(1.04);
    box-shadow: 0 0 0 14px rgba(204, 43, 94, 0);
  }

  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(204, 43, 94, 0);
  }
}

Este efecto puede ayudar a destacar una llamada a la acción, pero debe usarse con moderación. Si todos los botones de una web tienen animaciones infinitas, el efecto deja de ser útil y puede resultar invasivo.

Una alternativa más equilibrada sería activar la animación solo en momentos concretos o aplicarla a un único CTA principal.

@keyframes y diseño de interfaces: no todo es decoración

Uno de los errores más habituales al hablar de animaciones CSS es pensar que solo sirven para “hacer bonito”. En realidad, el movimiento puede tener una función muy importante dentro de una interfaz.

Una buena animación puede:

  • Ayudar a entender que un elemento ha aparecido o desaparecido.
  • Indicar que una acción está en progreso.
  • Guiar la atención hacia una zona concreta.
  • Reforzar una interacción.
  • Hacer que los cambios de estado sean más naturales.

Por ejemplo, cuando se abre un menú lateral, una animación de entrada puede ayudar a entender de dónde viene ese panel. Cuando aparece un mensaje de confirmación, una pequeña transición puede hacer que el cambio sea más claro. Cuando se carga contenido, un loader evita que el usuario piense que la página se ha quedado bloqueada.

La clave está en usar las animaciones con keyframes como parte de la comunicación visual, no como un adorno añadido al final.

Esto también tiene relación con el diseño UI/UX. Una herramienta como Figma puede ayudarte a pensar y prototipar estos comportamientos antes de llevarlos a código. Si te interesa esa parte del proceso, puedes ampliar con el artículo sobre pros y contras de usar Figma como herramienta de diseño UI/UX.

Cómo organizar keyframes en un proyecto CSS

En proyectos pequeños, puedes escribir los @keyframes cerca del componente o bloque donde se utilizan. Pero en proyectos más grandes, conviene mantener cierto orden.

Agrupar animaciones reutilizables

Si tienes animaciones que se repiten en varias partes del sitio, puedes crear una sección específica para ellas.

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(24px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Después puedes aplicarlas en distintos componentes.

.card {
  animation: slideUp 500ms ease-out forwards;
}

.modal {
  animation: fadeIn 300ms ease forwards;
}

Crear clases utilitarias

Otra opción es crear clases reutilizables.

.animate-fade-in {
  animation: fadeIn 400ms ease forwards;
}

.animate-slide-up {
  animation: slideUp 500ms ease-out forwards;
}

Esto puede ser útil si trabajas con una metodología de estilos más modular o si quieres aplicar animaciones de forma consistente.

Documentar las animaciones importantes

Si una animación tiene una función concreta dentro del diseño, merece la pena documentarla. No hace falta escribir una novela, pero sí dejar claro para qué sirve.

@keyframes cardEntrance {
  from {
    opacity: 0;
    transform: translateY(32px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Este tipo de organización ayuda a que otras personas del equipo entiendan por qué existe esa animación.

@keyframes en CSS y rendimiento web

El rendimiento es otro aspecto importante cuando hablamos de animaciones. Una animación puede verse muy bien en un ordenador potente, pero funcionar peor en dispositivos más antiguos o en móviles con menos recursos.

Por eso, al trabajar con @keyframes, conviene tener en cuenta tres ideas básicas.

Prioriza animaciones ligeras

Las propiedades transform y opacity suelen ser las mejores candidatas para animar porque permiten movimientos fluidos sin forzar tantos recálculos visuales.

En cambio, animar propiedades relacionadas con el layout, como width, height, top, left, margin o padding, puede generar más trabajo para el navegador.

No animes todo al cargar la página

Animar demasiados elementos al mismo tiempo puede ralentizar la experiencia inicial. Si todo entra, rebota, gira y aparece a la vez, la página pierde claridad.

Es mejor seleccionar algunos elementos clave y usar el movimiento para reforzar la jerarquía visual.

Comprueba la experiencia en móvil

Muchas veces diseñamos y probamos animaciones en escritorio, pero gran parte del tráfico llega desde móvil. Una animación que parece sutil en una pantalla grande puede resultar excesiva en una pantalla pequeña.

Por eso conviene probar siempre cómo se siente la animación en diferentes tamaños de pantalla.

Preguntas frecuentes sobre @keyframes en CSS

¿Qué diferencia hay entre @keyframes y animation en CSS?

@keyframes define los pasos de la animación, mientras que animation aplica esa animación a un elemento y controla aspectos como la duración, la repetición, el retraso o la curva de movimiento.

Dicho de otra forma: @keyframes describe qué ocurre y animation indica cómo y cuándo se ejecuta.

¿Puedo usar @keyframes para animar cualquier propiedad CSS?

Técnicamente, muchas propiedades CSS pueden animarse, pero no todas son igual de recomendables. Para obtener mejores resultados, suele ser preferible animar transform y opacity, porque ofrecen mejor rendimiento y suelen generar movimientos más fluidos.

Animar propiedades como width, height, top, left o margin puede ser más costoso para el navegador, sobre todo si se aplica a muchos elementos a la vez.

¿Cuándo debería usar @keyframes en lugar de transition?

Conviene usar @keyframes cuando necesitas una secuencia, una repetición o varios pasos intermedios. Por ejemplo, un loader giratorio, un efecto de pulso, una entrada elaborada o una animación que se repite.

En cambio, si solo quieres suavizar el cambio entre dos estados, como un hover o un menú que se abre y se cierra, probablemente sea mejor usar transition.

Cuando el movimiento también comunica

Aprender cómo funciona @keyframes en CSS es mucho más que memorizar una sintaxis. Es entender que el movimiento forma parte del diseño de una interfaz.

Una animación bien planteada no está ahí para llamar la atención porque sí. Está ahí para acompañar al usuario, explicar un cambio, suavizar una transición o reforzar una acción. Por eso, antes de añadir un efecto, conviene preguntarse qué aporta.

@keyframes CSS te da mucho control: puedes definir estados, crear secuencias, repetir movimientos y construir efectos visuales complejos sin necesidad de JavaScript. Pero ese control también requiere criterio.

Si estás empezando, quédate con esta idea: usa keyframes CSS cuando necesites controlar una animación paso a paso. Para cambios simples entre dos estados, una transition suele ser suficiente. Para secuencias, repeticiones y movimientos más elaborados, @keyframes es la herramienta adecuada.

Al final, animar bien no significa mover más cosas. Significa moverlas mejor. Y cuando el movimiento tiene intención, la interfaz se siente más clara, más fluida y mucho más cuidada.