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 los efectos de rebote y de resorte.

Aceleraciones en CSS

Al animar o hacer transiciones de elementos en CSS, puedes controlar la velocidad a la que cambia un valor con una función de aceleración usando las propiedades animation-timing-function y transition-timing-function.

Existen varias palabras clave disponibles como ajustes predeterminados en CSS: 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 toma 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, ya que parece tomar impulso.

En CSS, no es posible crear curvas complejas, como efectos de rebote o de resorte, pero, gracias a linear(), ahora puedes realizar una aproximación asombrosamente bien.

Una introducción a linear()

Navegadores compatibles

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

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 único número que puede variar 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 el valor de salida de 0.25 se usará en la marca del 50%.

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

Visualización en un gráfico de lineal(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).

Al especificar dos valores como longitud de parada, debes definir el punto de partida y el de finalización:

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

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

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

Cómo crear curvas complejas con linear()

Si bien los ejemplos anteriores son aceleraciones muy simples, puedes usar linear() para recrear funciones de aceleración complejas de una manera muy sencilla, 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, 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;
}

Aunque el código no te diga mucho, una visualización sí. Este es el resultado, visualizado como una curva azul:

Una curva de rebote suave dibujada en azul.

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

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

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

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

Compara el cuadro animado verde con el azul y verás que no es tan suave.

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

Una curva actualizada, con el doble de paradas.

Con solo duplicar el número de paradas, obtendrás un resultado fluido.

El código que se usa para la animación 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 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 linear().

Captura de pantalla de la 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 determinar la cantidad de paradas que deseas y su precisión.

En la parte superior derecha, también puedes elegir uno de los ajustes predeterminados: se incluyen Spring, Bounce, Simple elástico o Material Design con énfasis en la aceleración.

Compatibilidad con Herramientas para desarrolladores

En Herramientas para desarrolladores, se ofrece compatibilidad con 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 `linear()` de Chrome Herramientas para desarrolladores.
Captura de pantalla del editor `linear()` de Chrome Herramientas para desarrolladores.

Esta función de Herramientas para desarrolladores está disponible en el envío de Herramientas para desarrolladores con Chrome 114.

Foto de Howie Mapson en Unsplash