En CSS existen los denominados Motion Paths, o lo que es lo mismo, trayectos animados. Mediante esta característica podemos crear trayectos, rutas o caminos animados, por donde un elemento puede pasar.
Para crearlos, utilizaremos una familia de propiedades CSS prefijadas por offset-
:
Propiedad | Descripción |
---|---|
offset-path |
Define un trayecto, ruta o camino, utilizando la función ray() , path() o url() . |
offset-distance |
Indica la posición actual en el trayecto. |
offset-rotate |
Define la orientación del elemento del trayecto. |
offset-position |
Define el punto de inicio del trayecto. |
offset-anchor |
Define el punto de anclaje (punto de origen) del elemento que se mueve por el trayecto. |
offset |
Propiedad de atajo de las anteriores. |
El soporte de esta característica es buena en navegadores actuales, sin embargo, presta atención porque algunas características podrían no estar completamente soportadas:
Para utilizar CSS Motion Paths, lo primero que tenemos que hacer es definir un trayecto mediante la propiedad offset-path
. Este trayecto definirá la zona por la que se puede mover el elemento al que se lo apliques. En nuestro caso, vamos a imaginar que tenemos un elemento .container
que contiene un elemento .box
, que es el que se va a mover por nuestro trayecto:
.container {
display: flex;
justify-content: center;
align-items: center;
background: #aaa;
min-height: 400px;
}
.box {
width: 50px;
height: 50px;
background: indigo;
animation: move 2s alternate infinite;
}
@keyframes move {
0% { offset-distance: 0%; }
100% { offset-distance: 100%; }
}
En este código no hacemos nada extraño. En el padre, establecemos un flex
centrado, color de fondo y un alto mínimo para que se vea. En los elementos hijos .box
un tamaño, un color de fondo para distinguirlo y aplicamos una animación que explicaremos más tarde. De momento, sólo tenemos que saber que la animación se mueve desde el principio del trayecto hasta el final.
La propiedad offset-path
nos permite definir un trayecto de varias formas:
ray()
que define un segmento en una dirección de ángulo concreta.path()
donde definimos un trayecto SVG.url()
donde indicamos un archivo SVG que contiene un trayecto.Esto se traduce a los valores que puede tomar la propiedad offset-path
:
Valores | Descripción |
---|---|
none |
No establece ningún trayecto. Es el valor por defecto. |
ray( ) |
Indica un segmento en dirección |
ray( contain) |
Idem, pero manteniendo el elemento dentro del contenedor. |
path( ) |
Define un trayecto SVG. |
url( ) |
Define un SVG con el id de un trayecto path con el atributo d . |
Veamos cada una de ellas a continuación.
ray()
La función ray()
nos permite definir un trayecto como una porción de un círculo, estableciendo un ángulo como hacíamos con los gradientes cónicos.
Por ejemplo, asumamos que tenemos 3 cajas .box
dentro de un .container
. Observa el siguiente fragmento de código que añadiremos al anterior donde damos estilo a cada uno de los elementos hijos .box
:
.box-1 {
background: indigo; /* violeta */
offset-path: ray(90deg closest-side);
}
.box-2 {
background: crimson; /* rojo */
offset-path: ray(180deg closest-side);
}
.box-3 {
background: deeppink; /* rosa */
offset-path: ray(245deg closest-side);
}
En cada uno de estos elementos hijos .box
, hemos definido que se mueva en una dirección indicada por la función ray()
, que indica el ángulo de dirección e incluso el tamaño que tendrá con palabras clave como closest-side
, closest-corner
, farthest-side
, farthest-corner
o sides
:
Observa que las cajas .box
quedan ligeramente fuera del círculo rojo. Si añadimos la palabra clave contain
como último parámetro de la función ray()
, conseguiremos que se ajusten al interior del círculo.
Si no sabes como funcionan los parámetros de
mencionados anteriormente, echa un vistazo a formas y tamaños del gradiente radial, ya que lo explicamos ahí más detalladamente.
path()
Otro caso, quizás el más utilizado, es el de definir trayectos con la función path()
, que no es más que una especie de mezcla entre CSS y SVG. Con la función path()
se puede declarar en un d
de una etiqueta <path>
. De esta forma, puedes definir trayectos muy específicos, con líneas, curvas y formas mucho más complejas (o imposibles) de hacer en HTML.
Por ejemplo, observa este fragmento de código, donde a parte del tamaño, y animación que ya teníamos, aplicamos una función path()
en la propiedad offset-path
:
.box {
width: 50px;
height: 50px;
animation: move 2s alternate infinite;
background: url("robot.png");
background-size: 50px;
offset-path: path("m 0 0 h 150 v 100");
}
Veamos esos cambios detalladamente:
background-size
.m 0 0 h 150 v 100
.Ese trayecto significa que lo colocamos en las coordenadas 0x0
, que lo movemos 150px
en horizontal y que lo movemos 100px
en vertical. Puedes comprobar este trayecto con un editor SVG o con este editor online llamado SVG Path Editor. Hemos creado un trayecto desde la posición original del .box
hasta el final del trayecto definido. El resultado es el siguiente:
Gracias a la animación, que analizaremos más adelante, la caja .box
se moverá desde su posición inicial hasta el final del trayecto, de forma repetitiva.
url()
El caso de la función url()
es exactamente el mismo que el del caso anterior, con algunas diferencias:
url()
define el fichero de imágen SVG y el id
a usar: url("image.svg#pathname")
.image.svg
.<path>
con el id
indicado. En el ejemplo: id="pathname"
.d
de esa etiqueta SVG.La propiedad offset-distance
nos permite indicar el tamaño o porcentaje recorrido en el trayecto desde la posición inicial hasta la posición final. En los ejemplos anteriores la hemos utilizado en la animación, es la propiedad que se encarga de mover el elemento a través del trayecto.
Lo más cómodo es establecer la distancia con un porcentaje:
@keyframes move {
0% { offset-distance: 0%; }
100% { offset-distance: 100%; }
}
En este ejemplo, establecemos que la animación empieza con el elemento al inicio del recorrido (0%) y termina al final del recorrido (100%).
La propiedad offset-rotate
es una propiedad que se encarga de definir como vamos a rotar el elemento respecto a su trayecto. Por defecto, el valor utilizado en esta propiedad es auto
, por lo que veremos que al añadir un trayecto, el elemento se puede ver rotado.
Por ejemplo, si añadimos la propiedad offset-rotate
con el valor 0deg
, estaremos indicando al navegador que a ese elemento no queremos que se aplique ningún tipo de rotación.
Los valores que puede tomar son los siguientes:
Valor | Descripción |
---|---|
auto |
El valor auto es el valor por defecto. El elemento rota según el trayecto definido. |
auto |
Prefijado del valor auto , se le suma el ángulo indicado en |
reverse |
El valor reverse es justo el inverso al valor auto . |
reverse |
Idem a auto |
Se establece exactamente el ángulo de rotación de |
Veamos un ejemplo utilizando la propiedad offset-rotate
en la animación definida:
@keyframes move {
0% {
offset-distance: 0%;
offset-rotate: 90deg;
}
100% {
offset-distance: 100%;
offset-rotate: 0deg;
}
}
Mediante la propiedad offset-anchor
podemos establecer un punto de origen para el elemento que se mueve en el trayecto. Por ejemplo, observa la siguiente imagen y ten en cuenta los valores indicados de la propiedad a la derecha (valor de eje X, valor de eje Y).
100% 100%
: El punto que se moverá por el trayecto es la esquina inferior-derecha.50% 50%
: El punto que se moverá por el trayecto es el centro de la imagen.50% 0%
: El punto que se moverá por el trayecto es la antena del robot.Aunque aparentemente el soporte de esta característica es bastante pobre, parece que Chrome está comenzando a soportarlo en recientes versiones:
Por otro lado, la propiedad offset-position
nos permite establecer la posición inicial donde comenzará el punto inicial del trayecto. Esto puede ser útil para posicionar los trayectos, en el caso de que no se ajusten exactamente a la posición de entrada que se define en el elemento.
Valor | Descripción |
---|---|
auto |
El valor auto es el valor por defecto. |
Indicamos la distancia a mover la posición inicial del trayecto. |
Ten en cuenta que de tener el elemento con position
a static
, los valores de offset-position
no se tendrán en cuenta y serán ignorados.
Como muchas otras propiedades CSS, podemos utilizar la propiedad de atajo offset
que nos permiten escribir todas las propiedades individuales que se necesiten en una misma propiedad:
.box {
offset: <position> <path> <distance> <rotate> / <anchor>;
offset: auto path("m 0 0 h 100 v 200") 0% 45deg / 50% 50%;
offset: ray(45deg closest-side) / 40px 20px;
}
Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.
Puedes encontrar más sobre mi en Manz.dev