Cómo crear curvas de animación complejas en CSS con la función de aceleración linear()

Presentamos linear(), una función de aceleración en CSS que interpola de forma lineal entre sus puntos, lo que te permite recrear efectos de rebote y resorte.

Aceleraciones en CSS

Cuando animas o haces una transición de elementos en CSS, controlas la velocidad a la que cambia un valor con una función de aceleración que usa las propiedades animation-timing-function y transition-timing-function.

Hay varias palabras clave disponibles como ajustes predeterminados en CSS, como linear, ease, ease-in, ease-out y ease-in-out. Para crear tus propias curvas de aceleración, usa la función cubic-bezier() o adopta un enfoque basado en pasos con la función de aceleración steps().

Cuando se usan de forma adecuada, las aceleraciones le dan a un elemento animado una sensación de peso a medida que parece ganar impulso.

No es posible crear curvas complejas, como efectos de rebote o resorte, en CSS, pero gracias a linear() ahora puedes aproximarlas de forma asombrosa.

Introducción a linear()

Browser Support

  • Chrome: 113.
  • Edge: 113.
  • Firefox: 112.
  • Safari: 17.2.

Source

Una nueva forma de definir una aceleración en CSS es con linear(). Esta función acepta una cantidad de paradas, separadas por comas. Cada parada es un solo número que varía de 0 a 1. Entre cada parada, la interpolación se realiza de forma lineal, lo que explica el nombre de la función.

animation-timing-function: linear(0, 0.25, 1);

De forma predeterminada, estas paradas se distribuyen de forma equidistante. En el fragmento anterior, eso significa que el valor de salida de 0.25 se usará en la marca del 50%.

Visualizado, el gráfico de linear(0, 0.25, 1) se ve de la siguiente manera:

Visualización del gráfico de linear(0, 0.25, 1).

Si no quieres que las paradas se distribuyan de forma equidistante, puedes pasar de forma opcional una longitud de parada. Cuando pasas un valor como duración de la parada, defines su punto de partida:

animation-timing-function: linear(0, 0.25 75%, 1);

Aquí, no se usará un valor de salida de 0.25 en la marca 50%, pero sí en 75%.

Visualización del gráfico de linear(0, 0.25 75%, 1).

Cuando especificas dos valores como longitud de parada, defines tanto su punto de inicio como su punto final:

animation-timing-function: linear(0, 0.25 25% 75%, 1);

Se usará un valor de salida de 0.25 entre el 25% y el 75% del tiempo.

Visualización del gráfico de linear(0, 0.25 25% 75%, 1).

Cómo crear curvas complejas

Si bien los ejemplos anteriores son aceleraciones más simples, puedes usar linear() para recrear funciones de aceleración complejas si sacrificas algo de precisión.

Toma esta curva de aceleración de rebote, un tipo de aceleración que no se puede expresar directamente en CSS, definida con JavaScript:

function easing(pos) {
  const t = 7.5625;
  const e = 2.75;
  return pos < 1 / e
    ? t * pos * pos
    : pos < 2 / e
    ? t * (pos -= 1.5 / e) * pos + 0.75
    : pos < 2.5 / e
    ? t * (pos -= 2.25 / e) * pos + 0.9375
    : t * (pos -= 2.625 / e) * pos + 0.984375;
}

Si bien el código no te dice mucho, una visualización sí puede hacerlo. Este es el resultado, visualizado como una curva azul:

Una curva de rebote suave dibujada en azul.

La curva se puede simplificar agregándole varias paradas. Aquí, cada punto verde indica una parada:

Una curva de rebote suave en azul, con puntos verdes superpuestos.

Cuando se pasa a linear(), el resultado es una curva que se parece a la original, pero es un poco más áspera en los bordes.

Una curva simplificada en verde superpuesta sobre la curva suave original en azul.

Compara la caja verde animada con la azul. Verás que no es tan fluida.

Sin embargo, si agregas suficientes paradas, puedes aproximar la curva original bastante bien. Aquí tienes una versión actualizada:

Una curva actualizada, con el doble de paradas.

Con solo duplicar la cantidad de paradas, ya obtienes un resultado fluido.

El código que se usa para la animación se ve así:

animation-timing-function: linear(
  /* Start to 1st bounce */
  0, 0.004, 0.016, 0.035, 0.063 9.1%, 0.141, 0.25, 0.391, 0.563, 0.765, 1,
  /* 1st to 2nd bounce */
  0.891, 0.813 45.5%, 0.785, 0.766, 0.754, 0.75, 0.754, 0.766, 0.785, 0.813 63.6%, 0.891, 1 72.7%,
  /* 2nd to 3rd bounce */
  0.973, 0.953, 0.941, 0.938, 0.941, 0.953, 0.973, 1,
  /* 3rd bounce to end */
  0.988, 0.984, 0.988, 1
);

Una herramienta para ayudar

Crear manualmente esta lista de paradas sería muy engorroso. Afortunadamente, Jake y Adam crearon una herramienta para ayudarte a convertir una curva de aceleración en su contraparte de linear().

Herramienta de generación de aceleración lineal.
Captura de pantalla de https://linear-easing-generator.netlify.app/ en acción.

La herramienta toma una función de aceleración de JavaScript o una curva SVG como entrada y genera la curva simplificada con linear(). Usa los controles deslizantes para controlar la cantidad de paradas que deseas y su precisión.

En la esquina superior derecha, también puedes elegir uno de los ajustes predeterminados: se incluyen Spring, Bounce, Simple elastic o Material Design emphasized easing.

Compatibilidad con Herramientas para desarrolladores

En Herramientas para desarrolladores, se puede visualizar y editar el resultado de linear(). Haz clic en el ícono para mostrar una sugerencia interactiva que te permite arrastrar las paradas.

Editor lineal de las Herramientas para desarrolladores de Chrome.
Captura de pantalla del editor de `linear()` de las Herramientas para desarrolladores de Chrome.

Esta función de Herramientas para desarrolladores está disponible en Herramientas para desarrolladores a partir de Chrome 114.