CSS: Animaciones
Accessibilidad primero
No molestar
Primero de todo, las animaciones pueden ser molestas para algunos usuarios. Los navegadores tienen una opción para indicar a la página que el usuario prefiere reducir los elementos en movimiento.
Desde css podemos adaptar las animaciones para que sean menos violentas especializandolas dentro de un media query:
@media (prefers-reduced-motion: reduce) {
/* styles to apply if a user's device settings are set to reduced motion */
}
Para probar como se ve con dicha opcion Mozilla ha hecho una compilación de como activarla en diferentes platformas
Pausa-Para-Oculta
Si hay alguna animación que:
- Comienza automáticamente
- Dura más de 5s
- Se presenta en paralelo a otro contenido
Hay que proporcionar algún método para que el usuario la pause, pare o oculte.
Tres flashes o menos
Los elementos que parpadean son peligrosos para las personas con epilepsia.
Hay estudios que establecen el umbral seguro.
Es seguro si:
- No hay cosas que parpadeen mas de 3 veces por segundo.
- Flash general: Alternar luminancias
- Flash rojo: Alternar entre rojo saturado y otro color
- O el fulcrum que engloba los parpadeos no supera los 10 grados
Animación como forma de suavizar o naturalizar los cambios
Como lo molesto es el parpadeo, las animaciones justamente pueden ser útiles para hacer más naturales los cambios en las transiciones.
Objetivos en el diseño
Como pueden ser molestas es importante aplicar animaciones allí donde aporten algo:
- Continuidad: Cuando un elemento aparece, desaparece o cambia, hacerlo de una forma gradual para que la pagina no de saltos
- Feedback: Comunicar al usuario que la pagina responde a lo que hace (hover, clicked, drag...)
- Atención: Hay un elemento (uno, si, no dos) que queremos que capte la atención del usuario
- Esperas: En las esperas, indica que la aplicación no se ha colgado sinó que está esperando datos.
- Emoción: Refuerzan el mensaje y conectan con el usuario
- Marca: Las animaciones son parte de la marca
Respecto a las animaciones de espera:
- Tipos:
- Animación de carga: ofrecen algo interesante que mirar mientras se carga (por un ratín)
- Animación de progreso: Da cuenta de cuanto tiempo queda
- Esqueletos de carga (skeleton loaders): Muestran la maquetación aproximada de como serán los elementos que esta cargando.
- Criterios:
- Por bonica que sea, si es corta, mejor
- Esperar duele, hagamosla interesante
- Es parte de la marca
- Explicar a qué esperamos
- Si se conoce aprox, decir cuanto queda
Transiciones
Las transiciones son la forma más sencilla de generar animaciones. Las transiciones se activan cuando cambia el valor de una propiedad de un elemento y hacen que dicho cambio no se haga de golpe, sinó de forma progresiva.
Dichos cambios se producen, por ejemplo, cuando cambia el estado (:hover, :disabled, :active...) o cuando cambian las clases que se aplican al elemento.
La transición se define en el estado de llegada. Si queremos que se haga al entrar y salir del estado hay que poner transiciones en los dos entradas.
Propiedades de la transición
transition-properties
: Las propiedades que se cambiaran separadas por espacios.- Default:
all
- También podemos usar comas para separar grupos de propiedades que se animan de forma diferente. (Ver 'Multiples transiciones')
- Default:
transition-duration
: El tiempo que tarda en alcanzar el valor final.- Default: 0s
transition-delay
: Cuanto tarda la transición en empezar- Default: 0s
- Duraciones negativas no empiezan antes, pero empiezan con el timeline a medias como si hubieran empezado antes.
transition-timing-function
: la funcion que dicta como interpolar los valores entre el inicial y final.- Default:
easy
- Default:
transition
: Atajo para las anteriores. Si solo hay un tiempo es el duration.
Default to: all 0s 0s easy
Funciones de interpolación
Hay tres funciones de interpolación:
-
linear(v1, v2...)
- Incremento uniforme en los valores entre puntos de control
- Normalmente, el primer valor sera 0 y el ultimo 1
- Divide temporalmente el intervalo en tantos pasos como valores
linear(0, .4, 1)
(al 50% del progreso valdra .4)
- Si no nos va bien esa división, también podemos añadir al valor un porcentaje
linear(0, .5 40% 1)
mueve el punto que llegara al .5 a cuando llege el 40% del progreso
- Hace interpolación linial entre los pasos de un valor a otro
-
steps(nsteps, jumpmode)
:- hace la transición en nsteps saltos abruptos
- el jumpmode indica si hay o no salto al principio o al final
- jump-start/start: 5 -> 0%, 20%, 40%, 60%, 80% (no 100)
- jump-end/end: 5 -> 20%, 40%, 60%, 80%, 100% (no 0)
- jump-none: 4 -> 20%, 40%, 60%, 80% (neither 0 or 100)
- jump-both: 6 -> 0%, 20%, 40%, 60%, 80%, 100%
-
cubic-bezier(v1, t1, v2, t2)
- Los puntos iniciales de la curva son siempre (0,0) y (1,1)
- Lo que controlamos son las aristas de control (v1,t1) y (v2,t2)
- Según las aristas la funcion puede salirse del intervalo (0,1)
Tambien hay algunos alias con nombre para funciones típicas.
- linear:
- velocidad uniforme
- cubic-bezier(0.0, 0.0, 1.0, 1.0)
- linear(0, 1)
- ease:
- aceleracion suave al inicio y al final
- cubic-bezier(0.25, 0.1, 0.25, 1.0)
- a diferencia de ease-in-out, se esta mas tiempo en torno a los valores inicio y final
- ease-in
- lento al principio, rapido al final
- cubic-bezier(0.42,0,1,1)
- ease-out
- rapido al principio, suave al final
- cubic-bezier(0,0,0.58,1)
- ease-in-out
- suave al principio y al final (un poco mas lento que ease)
- cubic-bezier(0.42,0,0.58,1)
- step-start:
- Un salto brusco al inicio de la transicion
- step(1, start)
- step-end:
- Un salto brusco al final de la transicion
- step(1, end)
Multiples transiciones
Cada elemento puede tener más de una transición.
- En cada una de las propiedades
transition-*
puede definir transiciones independientes separandolas por comas - La propiedad
transition-property
es la que determina en el número de transiciones independientes - El resto de propiedades relacionadas,
- si hay de más se ignoran
- si hay de menos se repiten los valores en bucle
Animaciones basadas en fotogramas clave (keyframes
)
Las animaciones basadas en fotogramas clave dan más flexibilidad que las animaciones de transición pero son un poco más complejas de definir.
TODO: verificar que es asi
El timeline viene definido por el tiempo desde que se aplica el selector que contiene la animación.
Fotogramas clave (keyframes
)
Atributos
animation-name
: Nombre de la definición keyframesanimation-duration
: Obligatoria, sino por defecto es 0s y no hay animación.animation-delay
: igual que en la transicion (usando el shortcut, el segundo tiempo que indiquemos)animation-timing-funcion
: igual que en transiciones (default: ease)animation-iteration-count
: un numero (float!) o infinite (default 1)animation-fill-mode
:none
(default) Fuera del intervalo la animación no afecta a los atributosforwards
Las propiedades se quedan con el último valor de la animaciónbackwards
A la que aplica la animación y durante el delay, las propiedades adoptan el primer valor de la animaciónboth
: aplica backwards y forwards
animación-direction
: en que dirección progresan las distintas iteracionesnormal
-> -> (default)reverse
<- <-alternate
-> <-alternate-reverse
<- ->
animation-play-state
:running
(default)paused
Multiples animaciones independientes
Un keyframe puede controlar varias propiedades. Pero si queremos controlar propiedades con parametros de animación distintos, podemos separar los parametros de las animaciones independientes con comas.
Cuando varias animaciones o transiciones setean una misma propiedad,
el atributo animation-composition
especifica como mezclarlas.
replace
: (default) Sobreescribeadd
: concatena el valor
Esto es especialmente útil con attributos como transform
que se especifica con llamadas a diferentes funciones (translate, rotate...).
Por ejemplo si partimos de un transform: rotate(10) translateX(3)
y la animación aplica rotate(20)
replace
: substituira todas las funciones existentes:rotate(20)
add
: añadira las tranformaciones a las existentesrotate(10) translateX(3) rotate(20)
combine
: añadira a las funciones existentes que coincidan:rotate(30) translateX(3)
Animaciones de scroll
En las animaciónes clásicas, el progreso en la animación (timeline) lo determina el tiempo. Se define un inicio y una duración, y, las propiedades se modifican, segun el tiempo avance en ese intérvalo.
Sin embargo, en las animaciones de scroll el timeline no lo define el tiempo, sinó el desplazamiento de un scroll.
Recuerda
No solo el scroll de la pagina (:root
), sino el scroll de cualquier elemento que pueda generar un overflow.
Diferenciamos entre el elemento que genera el timeline y el elemento al que aplicamos la animación, que podria estar o no dentro el scroll.
Timelines scroll
y view
Tambien se definen dos tipos de timeline de scroll:
-
Desplazamiento (
scroll
):- El progreso lo determina la posición de un scroll
- El sujeto es el elemento que genera el overflow (scroller)
- 0% cuando está al inicio
- 100% cuando esta al final
-
Visibilidad (
view
):- El progreso lo determina la visibilidad parcial de un elemento en el scroller
- El sujeto es cualquier elemento dentro del que genera el overflow
- 0% cuando no es visible
- 100% cuando se ve completamente
Cómo definimos los timelines?
En el objeto que genera el timeline:
view-timeline: --my-timeline inline
scroll-timeline: --my-other-timeline y
Son atajos que juntan las propiedades con sufijos -name
y -axis
(y inset
para view).
*-name
: especifica un nombre (sintaxis de variable css) para referenciarla en las animaciones que la usen. (Por defecto,none
para anonimas)- Se especifica para el elemento subject
*-axis
: define que eje del scroll (x, y, block, inline) default:block
*-inset
: (solo para view) reduce (o amplia, si negativo) la zona del viewport en la que se produce la animación - Dos valores start y end - Si no se indica end es igual que start - Si no se indica ninguno,auto
- Si son negativos la animación empieza o acaba fuera del view port.
Ahora, si queremos usar uno de estos timelines en una animación,
hay que especificar la propiedad animation-timeline
indicando una de esas variables.
El animation-timeline
por defecto es auto
, que quiere decir que el timeline es el tiempo de documento, es decir, las animaciones clásicas.
És útil sobretodo para combinar animaciones con diferentes timelines de tiempo y de scroll/view,
que se indican separadas con comas como las otras propiedades de animacion.
TODO: none = auto??
Animation Range
animation-range{-start/-end}
: Define el intervalo considerado como inicio y final de tránsito.
Intervalos del scroll considerando el movimiento de un Subject (S) por un Puerto de scroll (P). Convención: en la dirección de scroll, P0 y S0 son sus bordes de inicio, P1 y S1 son sus bordes de final.
https://scroll-driven-animations.style/tools/view-timeline/ranges/
entry-crossing
: Mientras que el subject cruza la entrada del puerto- 0%
S0=P1
empieza a entrar todo el puerto - 100%
S1=P1
ha entrado todo en el puerto
- 0%
exit-crossing
: Mientras que el subject cruza la salida del puerto- 0%
S0=P0
empieza a salir del puerto - 100%
S1=P0
acaba de salir del puerto
- 0%
entry
: Como entry crosing pero- 0%
S0=P1
empieza a entrar en el puerto - 100%
(S<P) S1=P1
ha entrado todo en el puerto - 100%
(S>P) S0=P0
empieza a desaparecer
- 0%
exit
: Como exit crossing pero si es grande se espera a que haya entrado todo.- 0%
(S<P) S0=P0
empieza a salir del puerto - 0%
(S>P) S1=P1
ha entrado todo el puerto - 100%
S1=P0
acaba de salir del puerto
- 0%
contain
: Mientras que se vea entero, si no cabe, mientras cubra todo el puerto.- 0%
S<P S1=P1
- 100%
S<P S0=P0
- 0%
S>P S0=P0
- 100%
S>P S1=P1
- 0%
cover
: Durante el tiempo que se ve algo del componente- 0%
S0=P1
Empieza a entrar - 100%
S1=P0
Acaba de salir
- 0%
Timelines anónimos con las funciones scroll()
y view()
Algunas fuentes de timeline se pueden indicar sin darles nombre,
con las funciones view
o scroll
.
-
scroll(...)
:- Escoge un timeline scroll
- Tiene dos parametros: scroller y axis
- scroller
- nearest: el mas cercano de los ancestro que tenga scroll en el eje
- root: el documento
- self: el elemento animado
- axis:
- Ejes físicos:
x
yy
- Ejes lógicos:
inline
yblock
- Ejes físicos:
- Si no se indica cualquiera de los dos se coge su defecto (nearest block)
scroll()
meansscroll(nearest block)
scroll(root)
meansscrall(root block)
scroll(y)
meansscroll(nearest y)
- Se especifican en cualquier orden (son disjuntos)
-
view(...)
- Lo que controla la animacion es el tránsito de un elemento (subject) por la parte visible (scroll port) de un elemento contenedor con scroll
- No permite escoger
- ni elemento cuya visibilidad controla la animación (subject), que será self
- ni el scroller, que será nearest y defile lo que es el view port
- Tiene dos parametros inset y axis
- view-timeline-inset: son dos distancias (
-start
y-end
) positivas (o negativas) que reducen (o amplian) el scroll port- el scroll port es la zona que se consider por la que tiene que pasar o verse el subject
view-timeline-axis
como el scroll: x, y, inline, block; por defectoblock
- Firefox:
horizontal
,vertical
, hay que especificarlo a parte mientras no se actualiza para no invalidar la regla en otros navegadores
- Firefox:
Propiedad timeline-scope
Por defecto los timelines solo se pueden usar en animaciones de elementos descendientes.
La propiedad timeline-scope
tiene como valor el nombre de un timeline en un
elemento hijo, augmentando el alcance (scope) a
En el ejemplo anterior Scroller define un timeline.
Para poder afectar a Animated, el elemento scope tiene que definir timeline-scope
al nombre del timeline de Scroller.
Atrasando o adelantando el timeline view (inset
)
La propiedad view-timeline-inset
A veces queremos empezar o acabar la animacion view
un poco después o un poco antes de cuando se empieza a ver o ya se ve completamente.
view-timeline-inset: xdir ydir // positive inwards, negative outwards
View transitions
Las view transitions permite vincular elementos en paginas o layouts diferentes y animar la transición de uno a otro cuando se cambia de pagina o de estado.
La propiedad view-transition
es para un identificador (en este caso no es necesario los dobles --).
Si en el cambio de pagina o cambio de doom existen antes y despues elementos con el mismo identificador, se pruduce una animación de transición entre uno y el otro.