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.

Graduaciones en CSS

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

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

Cuando se usan de forma adecuada, las suavizaciones le dan a un elemento animado una sensación de peso, ya que parece que gana impulso.

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

Introducción a linear()

Navegadores compatibles

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

Una nueva forma de definir una suavizació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, se realiza la interpolación de manera lineal y se explica el nombre de la función.

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

De forma predeterminada, estas paradas se distribuyen de manera equidistante. En el fragmento anterior, eso significa que se usará el valor de salida de 0.25 en el 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 deseas que las paradas se distribuyan de manera equidistante, puedes pasar una duración de la parada. Cuando pasas un valor como longitud de parada, debes definir 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%, sino en 75%.

Visualización en un gráfico de lineal(0, 0.25 75%, 1).

Cuando especificas dos valores como una longitud de parada, defines su punto inicial y final:

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

Se usará un valor de salida de 0.25 del 25% al 75% en el tiempo.

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

Cómo crear curvas complejas con linear()

Si bien los ejemplos anteriores son suavizaciones muy simples, puedes usar linear() para volver a crear funciones de suavización complejas de una manera muy simple, con el compromiso de perder algo de precisión.

Tomemos esta curva de aceleración de rebote, un tipo de aceleración que no se puede expresar directamente en CSS, que se define mediante 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í podría hacerlo. Este es el resultado, visualizado como una curva azul:

Una curva de rebote suave dibujada en azul.

Para simplificar la curva, se pueden agregar varias paradas. Aquí, cada punto verde indica una parada:

Una curva de rebote suave en azul, con puntos verdes en la parte superior.

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 ubicada sobre la curva suave original en azul.

Compara el cuadro animado verde con el azul. Puedes ver que no es tan fluido.

Sin embargo, si agregas suficientes paradas, puedes aproximarte bastante a la curva original. Aquí hay una versión actualizada:

Una curva actualizada, con el doble de la cantidad de paradas.

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

El código que se usa para animar se ve de la siguiente manera:

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 de ayuda

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

Captura de pantalla de la herramienta generadora de suavizació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 parámetros predeterminados: se incluyen los efectos de suavización enfatizados de Spring, Bounce, Simple elastic o Material Design.

Compatibilidad con Herramientas para desarrolladores

En DevTools, se admite la visualización y edición del resultado de linear(). Haz clic en el ícono para ver información interactiva sobre la herramienta que te permite arrastrar las paradas.

Captura de pantalla del editor &quot;linear()`&quot; de Chrome DevTools.
Captura de pantalla del editor `linear()` de Chrome Herramientas para desarrolladores.

Esta función de DevTools está disponible en la versión que se envía con Chrome 114.

Foto de Howie Mapson en Unsplash