Transiciones CSS

Suavizar cambios de estilo en interacciones del usuario


Como vimos anteriormente, podemos utilizar pseudoclases como :hover para cambiar los estilos cuando el usuario mueva el ratón sobre el elemento HTML. Esto provoca un cambio de estilo que da feedback al usuario. Por defecto, este cambio de estilos se realiza de golpe, inmediatamente.

Mediante las transiciones CSS, uno de los aspectos más interesantes de CSS, podemos hacer que ese cambio de estilo no se realice de golpe, sino que lo haga de forma gradual, mediante atractivos efectos de transición que harán más elegantes y agradables nuestros diseños.

Propiedades de transición CSS

Las transiciones se basan en un principio muy básico: conseguir un efecto suavizado entre un estado inicial y un estado final al realizar una acción. Las propiedades CSS que podemos utilizar relacionadas con las transiciones son las siguientes:

PropiedadesDescripciónValor
transition-durationTiempo de duración.0 |
transition-propertyPropiedades CSS afectadas por la transición.all | none | propiedad css
transition-timing-functionRitmo de la transición.Ver funciones de tiempo
transition-delayTiempo de retardo inicial.0 |
transition-behaviorPermite realizar transiciones discretas.normal | allow-discrete

Por defecto, las transiciones están habilitadas para todas las propiedades CSS, sólo que tienen una duración de 0s. Salvo que cambiemos esta duración, los cambios de estilo se realizarán de golpe.

Veamos como funciona cada una de estas propiedades detalladamente.

La propiedad transition-duration

Con la propiedad transition-duration especificaremos la duración de la transición, desde el inicio de la transición, hasta su finalización. Recuerda que por defecto, las transiciones tienen una duración de 0s, por lo que si no cambias este valor, cambiará de golpe y será lo mismo que no tener transición.

.element {
  transition-duration: 0.5s;
  width: 200px;
  height: 200px;
  background: grey;
}

.element:hover {
  background: indigo;
}
<div class="element"></div>

Ojo: Si establecemos una duración demasiado alta, el navegador realizará la transición a trozos intermitentes, lo que hará que se vea a golpes. Se recomienda siempre comenzar con valores cortos, para que las transiciones sean rápidas y elegantes.

La propiedad transition-property

En primer lugar, la propiedad transition-property se utiliza para especificar la propiedad a la que que afectará la transición. Podemos especificar la propiedad concreta (width o color, por ejemplo) o simplemente especificar all para que se aplique a todos los elementos con los que se encuentre. Por otro lado, none hace que no se aplique ninguna transición.

PropiedadesValor
allAplica la transición a todas las propiedades css.
noneNo aplica transición. El cambio se producirá de golpe (brusco).
propiedad cssAplica la transición sólo a la propiedad css especificada.

Ten en cuenta que para la transición se efectue correctamente, deberíamos tener un estado inicial y un estado final, en caso contrario, el navegador podría no saber uno de esos estados y por lo tanto, no podría efectuar la transición. En algunos casos no será necesario el estado inicial puesto que tomará el valor por defecto.

Ten en cuenta que puedes animar todas las propiedades CSS afectadas utilizando all:

.element {
  /* Primer ejemplo: Anima todas las propiedades que cambien de estado */
  transition-property: all;
  transition-duration: 1s;

  /* Segundo ejemplo: Anima sólo el ancho, el resto no transicionan, cambian de golpe */
  transition-property: width;
  transition-duration: 1s;
}

Nota: Debes saber que no todas las propiedades CSS son animables (o transicionables). Por norma general, la mayoría de las propiedades que son cuantificables (valores numéricos, porcentajes, valores hexadecimales como colores, etc...) son animables. Por ejemplo, la propiedad background-image para gradientes no se puede animar actualmente.

La propiedad transition-delay

La propiedad transition-delay nos ofrece la posibilidad de retrasar el inicio de la transición un número de segundos determinado. Si se omite, la transición comienza inmediatamente.

Veamos un pequeño ejemplo de todas estas propiedades de transición:

.element {
  display: inline-block;
  background: #777;
  padding: 1rem;

  transition-property: all;
  transition-duration: 0.5s;
}

.element:hover {
  background: indigo;
  padding: 2rem 4rem;
  color: #fff;
}
<div class="element">Hover me!</div>

En este ejemplo, con all hemos determinado animar todas las propiedades que cambien:

  • La propiedad background de color de fondo cambiará de #777 a indigo
  • La propiedad color de color de texto cambiará, de #000 (por defecto) a #fff.
  • La propiedad padding del tamaño del relleno cambiará de 1rem a 2rem 4rem
  • La propiedad display no cambiará, puesto que es inline-block en ambas.

El segundo es un caso especial, puesto que no tiene valor inicial definido, y toma el estilo inicial por defecto, que es color #000. Cada una de estas transiciones cambiantes se realizarán durante 0.5s de duración, como indicamos con transition-duration.

La propiedad transition-behavior

Existe una nueva propiedad transition-behavior que permite realizar transiciones en propiedades con valores discretos. ¿Esto que significa? Tradicionalmente, en CSS, sólo se podían crear transiciones en propiedades que tengan valores cuantificables, como por ejemplo:

  • opacity: Valores decimales entre 1 y 0 o porcentajes entre 0% y 100%.
  • background o color: Los colores son valores hexadecimales (numéricos), por lo que son cuantificables.
  • padding o margin: Son tamaños, cantidades numéricas.

Sin embargo, propiedades como display, que tienen valores como none, block, flex, no era posible animarlos. Ahora, con la propiedad transition-behavior y mediante su valor allow-discrete si será posible.

Por defecto, la propiedad transition-behavior tiene valor normal y no anima estas propiedades con valores discretos. Sin embargo, si activamos su valor allow-discrete, si lo hará.

Veamos un ejemplo en el que activamos allow-discrete cuando el <input> checkbox está marcado:

dialog {
  display: none;
  opacity: 0%;
  transition-duration: 1s;
  transition-property: opacity, display;
}

input:checked ~ dialog {
  transition-behavior: allow-discrete;
}

dialog[open] {
  opacity: 100%;
  display: block;
}
const button = document.querySelector("button");
const dialog = document.querySelector("dialog");
button.addEventListener("click", () => dialog.toggleAttribute("open"));
<button>Mostrar/ocultar diálogo</button>
<input class="discrete" type="checkbox"> Usar allow-discrete

<dialog>Hello friends!!!</dialog>

Marca y desmarca la casilla Usar allow-discrete, para ver la diferencia de usar la transición junto a opacity sin allow-discrete y con allow-discrete.

Atajo: La propiedad transition

Como siempre, podemos resumir todas estas operaciones en una propiedad de atajo denominada transition. Los valores del ejemplo superior, se podrían escribir como se puede ver a continuación (si no necesitas algún valor, se puede omitir):

.box {
  /* transition: <property> <duration> <timing-function> <delay> <behavior> */
  transition: all 0.5s linear;

  background: grey;
  width: 200px;
  height: 200px;
}

.box:hover {
  background: indigo;
}
<div class="box"></div>

Observa que estamos omitiendo los dos últimos valores. Si quisieramos un retardo de 2s a la hora de hacer una transición, bastaría con añadir un 2s después de linear. Y si además, quisieramos permitir valores discretos como los de la propiedad display, bastaría con añadir un allow-discrete al final.

La propiedad transition-timing-function se puede utilizar también en animaciones mediante animation-timing-function, y no sólo en transiciones. Como es algo compleja, la explicaremos más adelante, en su propio tema.

¿Quién soy yo?

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