Sebastian Gomez
Todo sobre transiciones en CSS
Las transiciones forman parte del conjunto de herramientas que tenemos como desarrolladores frontend para mejorar la experiencia del usuario dentro de nuestra aplicación web. Son útiles porque nos permiten animar el cambio de valores en las distintas propiedades de un elemento, lo que puede hacerlo más llamativo al usuario e invitarlo a interactuar con él. En este post abordaremos el extenso tema de las transiciones con diversos ejemplos adaptados desde la especificación.
Comencemos con un ejemplo simple
Tenemos un cuadrado simple:
<div id="square1" class="square red"></div>Y unos estilos asociados a dicho cuadrado:
/* Define la regla de estilo para la clase "square" */
.square {
/* Establece el ancho en 50 píxeles */
width: 50px;
/* Establece la altura en 50 píxeles */
height: 50px;
/* Establece un margen inferior de 5 píxeles */
margin-bottom: 5px;
}
/* Define la regla de estilo para la clase "red" */
.red {
/* Establece el color de fondo en rojo */
background: red;
}Además, tenemos una clase adicional que asignaremos al cuadrado en un momento específico en el tiempo:
/* Define la regla de estilo para la clase "black" */
.black {
/* Establece el color de fondo en negro */
background: black;
}Sin embargo, queremos que este cambio se realice de una manera suave, controlada y agradable al usuario. Por tanto, aquí es donde necesitamos hacer uso de las transiciones. Esto lo podemos hacer añadiendo la propiedad transition dentro de la clase que queremos aplicar:
/* Define la regla de estilo para la clase "black" */
.black {
/* Establece el color de fondo en negro */
background: black;
/* Establece una transición para la propiedad "background" */
transition: background 2s 0.25s;
/* ^^^^^^^^^^ ^^ ^^^^^ */
/* Propiedad Duración Retraso */
}La propiedad transition nos permite que el cambio de background de rojo a negro se haga durante 2 segundos (duración) en vez de hacerse instantáneamente. Además, nos permite indicar que este cambio empiece a ocurrir 0.25 segundos después de que se asigne la clase al elemento (delay). Existe otra sintaxis alternativa para esto que requiere unas cuantas líneas más, pero es útil conocerla:
/* Define la regla de estilo para la clase "black" */
.black {
/* Establece el color de fondo en negro */
background: black;
/* Establece la propiedad que se animará en la transición, en este caso "background" */
transition-property: background;
/* Establece la duración de la transición, en este caso 2 segundos */
transition-duration: 2s;
/* Establece el tiempo de espera antes de iniciar la transición, en este caso 0.25 segundos */
transition-delay: 0.25s;
}Al dominar las transiciones en CSS podrás mejorar la experiencia del usuario en tus aplicaciones web y lograr efectos más atractivos y dinámicos.
Analogías de valores en transiciones CSS
Al igual que hemos asignado valores en segundos a la duración y al retraso (delay), podríamos haberlo hecho en milisegundos (ms). Para ello, bastaría con multiplicar por 1000 y añadir ms al final. Por ejemplo:
/* Establece la duración de la transición en 2000 milisegundos (2 segundos) */
transition-duration: 2000ms;
/* Establece un retraso antes de que comience la transición de 250 milisegundos (0.25 segundos) */
transition-delay: 250ms;Si queremos aplicar transiciones sobre más de una propiedad, podemos usar all para indicar que la transición se aplica sobre todas las propiedades posibles:
/* Define la regla de estilo para la clase "black" */
.black {
/* Establece el color de fondo en negro */
background: black;
/* Establece el color del texto en blanco */
color: white;
/* Establece una transición para todos los cambios de propiedades. */
/* La duración es de 2 segundos y se retrasa 0.25 segundos antes de comenzar */
transition: all 2s 0.25s;
}Nota: El uso de transition: all no es recomendable desde el punto de vista del desempeño (performance). Es altamente recomendable no usar transition: all a menos que definitivamente quieras aplicar transiciones sobre todas las propiedades del elemento de la misma manera. A continuación te explico cómo hacer transiciones específicamente con cada propiedad.
A veces no deseamos que se apliquen transiciones sobre todas las propiedades de la misma manera. La propiedad transition también nos permite especificar la transición de cada propiedad simplemente separándolas por comas. Veamos un ejemplo:
/* Define la regla de estilo para la clase "black" */
.black {
/* Establece el color de fondo en negro */
background: black;
/* Establece el color del texto en blanco */
color: white;
/* Define una transición distinta para el fondo y para el color del texto */
transition:
/* Transición de 2 segundos para el fondo con un retardo de 0.25 segundos */
background 2s 0.25s,
/* Transición de 1.5 segundos para el color del texto con un retardo de 3 segundos */
color 1.5s 3s;
}En el ejemplo anterior estamos cambiando el background y el color con distinta duración y distinto retraso (delay). Esto permite tener un control más granular de exactamente lo que necesitamos animar en cada transición.
La función de tiempo: transition timing function
Hasta ahora las transiciones de las que hemos hablado ocurren de manera lineal, es decir, el cambio ocurre uniformemente durante el tiempo que dure la transición. Sin embargo, no es la única manera de hacerlo. Podemos acelerar el cambio al comienzo y desacelerarlo al final, lo que nos dará un tipo diferente de sensación al ver la transición. Para determinar cómo ocurrirá el cambio, tenemos la propiedad transition-timing-function, que puede tomar los siguientes valores:
/* "linear": la velocidad de transición es constante a lo largo de toda la animación */
transition-timing-function: linear;
/* "ease-in": la velocidad de transición aumenta gradualmente al inicio de la animación */
transition-timing-function: ease-in;
/* "ease-out": la velocidad de transición disminuye gradualmente al final de la animación */
transition-timing-function: ease-out;
/* "ease-in-out": la velocidad aumenta gradualmente al inicio y disminuye gradualmente al final */
transition-timing-function: ease-in-out;
/* "cubic-bezier": una curva personalizada definida por los puntos de control especificados */
transition-timing-function: cubic-bezier(0.21, 0.3, 0.1, 0.23);Pero esta no es la única manera de añadir esta propiedad a las transiciones. También es posible hacerlo directamente en la propiedad transition:
/* Define la regla de estilo para la clase "move" */
.move {
/* Desplaza el elemento 500 píxeles a lo largo del eje X */
transform: translateX(500px);
/* Configura una transición animada para la propiedad transform */
transition: transform 2s 0.25s ease-in-out;
}Incluso en cada transición sobre las propiedades:
/* Define la regla de estilo para la clase "move-background" */
.move-background {
/* Desplaza el elemento 500 píxeles a lo largo del eje X */
transform: translateX(500px);
/* Establece el color de fondo en rojo */
background: red;
/* Configura una transición distinta para transform y para background, cada una con su propia función de tiempo */
transition: transform 2s 0.25s ease-in-out, background 1s 0.1s cubic-bezier(0.21, 0.3, 0.1, 0.23);
}Entendiendo cubic bezier()
Profundicemos un poco en cómo funciona la propiedad transition-timing-function cuando toma el valor de cubic-bezier(). Para ello, revisemos en qué consiste la curva de Bézier en la cual se basa esta función.
Las curvas de Bézier son un sistema matemático desarrollado por Pierre Bézier para el trazado de dibujos de aeronaves y automóviles. La función cubic-bezier() de CSS toma cuatro números:
cubic-bezier(x1, y1, x2, y2);Esos cuatro valores son las coordenadas de los dos puntos de control intermedios, P1 (x1, y1) y P2 (x2, y2). Los otros dos puntos de la curva, P0 y P3, están fijos en (0, 0) y (1, 1) respectivamente, así que no se pasan como argumentos. Con las coordenadas de P1 y P2 se puede definir completamente la forma de la curva y, por tanto, distintos tipos de transición.
En estos sitios web puedes experimentar más con este tipo de transiciones, donde puedes ajustar los valores para tener un mayor control en tu curva:
Debes tener en cuenta que hay propiedades que no son animables, es decir, no puedes aplicarles transiciones. Para ver una lista de cuáles propiedades son animables y cuáles no, puedes revisar este enlace de MDN:
Nota: la lista oficial vive en MDN bajo "Animatable CSS properties". Esa página explica los tipos de animación; para saber si una propiedad concreta es animable, mira la fila "Animation type" en la tabla "Formal definition" de su página de referencia.
En el siguiente ejemplo se muestra un conjunto de transiciones sobre cubos con distintas transition-timing-function y propiedades. Puedes jugar con ellas para evidenciar sus diferencias:
Depurando transiciones
Las herramientas para desarrolladores de los navegadores, como Chrome y Firefox, nos permiten ralentizar o acelerar las transiciones para depurarlas (debug) más fácilmente. Para ello, puedes abrir la pestaña de animaciones.
También puedes usar JavaScript para conocer el estado de una transición mediante los siguientes eventos:
transitionstarttransitionend
Algunas consideraciones
Finalmente, algunas consideraciones respecto a las transiciones:
- Las transiciones de alrededor de 100ms son prácticamente instantáneas para los usuarios y difícilmente perceptibles.
- Las transiciones de máximo 1 segundo y mínimo 250ms son buenas y mantienen a los usuarios conectados.
- Más de 2 segundos es definitivamente una mala idea para sitios web estándar, ya que puede desconectar al usuario de lo que pasa.
- De 250ms a 300ms es el tiempo estándar de la mayoría de las animaciones.
- Las transiciones, en general, te permiten crear experiencias que ocurren solo una vez.
- Si el navegador no soporta transiciones, en el peor de los casos siempre se cambia la propiedad de forma directa.
- Las transiciones son granulares porque te permiten animar una, dos o múltiples propiedades.
Ejercicios propuestos
- Crea un cuadrado que cambie de color y de tamaño al pasar el mouse, usando una única transición con
transition: all, y luego refactorízalo para animar cada propiedad por separado. - Experimenta con
transition-timing-functionaplicandoease-in,ease-outyease-in-outal mismo elemento y compara la sensación de cada una. - Crea tu propia curva en cubic bezier.com y aplícala a una transición de
transform: translateX(). - Usa los eventos
transitionstartytransitionenden JavaScript para registrar en consola cuándo empieza y termina una transición.
Resumen en 3 puntos
- La propiedad
transition(y sus variantestransition-property,transition-duration,transition-delayytransition-timing-function) anima el cambio de valores de una propiedad de forma suave y controlada. - Evita
transition: allpor rendimiento; prefiere declarar cada propiedad por separado, separándolas con comas. cubic-bezier(x1, y1, x2, y2)define la curva con las coordenadas de los puntos de control P1 y P2 (P0 y P3 están fijos en(0,0)y(1,1)), dándote control total sobre la sensación de la transición.
Eso es todo. Espero que este post te sea de utilidad y lo puedas aplicar a algún proyecto que tengas en mente, o que simplemente te haya ayudado a entender la naturaleza de las transiciones en CSS.
Déjame un comentario si lograste implementarlo, si quieres añadir alguna otra funcionalidad o si tienes alguna duda. Y recuerda que si te gustó, también puedes compartir este artículo usando los enlaces a las redes sociales aquí abajo.
¡Buena suerte en tus proyectos y no olvides seguir experimentando y aprendiendo sobre las transiciones en CSS!
Sebastian Gomez
Creador de contenido principalmente acerca de tecnología.