CSS Transitions

21/01/2015
CSS Transitions Drupal

Hace un tiempo, si querías algo de movilidad dentro de los elementos de una página web, tenías dos opciones: una opción algo limitada y que a muchos diseñadores les daba miedo como jQuery (en sus versiones de UI y otras tantas), y una opción tan loca como Flash (poco a poco erradicada). Las animaciones y cambios de elementos eran algo que muchos teníamos que implementar y no teníamos demasiados medios para ello. 

Digamos que tenemos tres capas: el contenido (HTML), la presentación (CSS) y el comportamiento (JS). Una animación pertenecería siempre a la presentación, y sin embargo nos hemos visto obligados (y a día de hoy es así en algunos casos) a mezclar comportamiento y presentación (estilos y Javascript). Pongamos por caso un botón que cuando está activo haciendo click cambia de posición y de color: tanto la posición y el color inicial como los finales deben estar especificados en CSS, y el cambio de inactivo a activo, una cuestión de comportamiento (JS). 

Sería natural si este artículo os resultara muy sencillo; no os preocupéis, este artículo servirá de base para ir avanzando y profundizando en estos temas. 

Las bases

Vamos al caso más sencillo: un botón que tiene un hover. 

=same($values...)
  $length: length($values)
  $value: nth($values, $length)
  @for $i from 1 to $length
    #{nth($values, $i)}: $value
=btn($bg: red, $fsize: 14px)
  +box-sizing(border-box)
  +same(border, outline, text-decoration, none)
  +same(font-size, line-height, $fsize)
  +border-radius(#{$fsize/3})
  +box-shadow(0 0 #{$fsize/3} #888)
  color: white
  font-weight: bolder  
  background-color: $bg
  padding: .5em 1em
.icon
  margin: 50px
  display: inline-block
  &.cancel
    +btn(red, 50px)
    &:hover
      +btn(black, 50px)
<button class="icon cancel" href="">Cancelar</button>

En este caso, al posar el ratón sobre el botón el cambio es instantáneo y bastante forzado. Poco fluido, que diríamos.

Aquí es donde entran en juego las CSS transitions, una propiedad que permite crear transiciones entre estilos para un elemento. Su sintaxis es sencilla y establece cuatro datos básicos: 

    transition: <transition-property> <transition-duration> <transition-timing-function> <transition-delay>

<transition-property> La propiedad CSS a la que la transición debe afectar. Si debe afectar a todas será 'all'.
<transition-duration> Duración de la transición en segundos (s) o mili-segundos (ms). 
<transition-timing-function> Gráfica de velocidad a la que la transición se realizará; hay valores predefinidos para esto como 'ease', 'ease-in-out' y algunos otros, pero pueden definirse métodos propios con steps() y 
cubic-bezier().
<transition-delay> Tiempo que la transición retrasará su comienzo.

Gracias a transition-property podemos definir varias transiciones para un mismo elemento, ya que cada una podrá afectar a aquellas propiedades que nos interese. Igualmente, todos los campos que hemos detallado son optativos, si no se especifican cogerán los valores por defecto. Para el ejemplo anterior concretamente, los valores por defecto nos sirven sin problema, con lo que simplemente añadiendo

  +transition()

tendrá una transición bastante bonita y fluida. Si la declaración de la transición la hacemos en la clase en sí, la transición ocurrirá tanto en el evento hover-in como en el hover-out; sin embargo, si la declaramos solo en el &:hover, está solo ocurrirá en el hover-in. Algo bastante habitual es tener dos transiciones diferentes, una para el hover-in y otra para el hover-out, dejando un pequeño retraso en la segunda.

Composición de transiciones

En el caso de que tengamos varios cambios que queramos coordinar entre sí, lo haremos jugando con los delay y declarando las transiciones con cuidado para solaparlas bien. 

=btn($bg: red, $fsize: 14px)
  +box-sizing(border-box)
  +same(border, outline, text-decoration, none)
  +same(font-size, line-height, $fsize)
  +border-radius(#{$fsize/3})
  +box-shadow(0 0 #{$fsize/3} #888)
  color: white
  font-weight: bolder  
  background-color: $bg
  padding: .5em 1em
  +transition(background .5s ease,padding 1s ease-in-out .5s)
.icon
  margin: 50px
  display: inline-block
  &.cancel
    +btn(red, 50px)
    &:hover
      background-color: black
      padding-right: 200px

En esta pequeña modificación veis que en el evento :hover cambiamos color de fondo y padding-right. Tan solo tenemos que declarar dos transiciones: primero una sin <transition-delay> para el 'background' que durará .5s (medio segundo) y en segundo lugar una transición para el padding con un retraso de .5s, la misma duración que tiene la primera transición. Esto puede complicarse tanto como queráis, llegando a hacer animaciones tremendamente elaboradas. 

El evento Click

En CSS no existe el :click, esto se lo dejamos a Javascript. Existen formas de emularlo mediante composiciones de checkbox de formularios y los atributos :checked de CSS, pero de forma nativa, no existe forma de detectar un Click en un elemento desde CSS. Para eso, para el comportamiento, tenemos Javascript (con jQuery en este caso): 

$('button').click(function(e){
  e.preventDefault();
  $(this).toggleClass('clicked');
  return false;  
});

Y en el ejemplo anterior, de nuevo, modificamos para añadir esta nueva clase "clicked": 

&:hover,&.clicked
 background-color: black
 padding-right: 200px

Por simplificar, en esta ocasión lo vamos a colocar de manera que al hacer click y retirar el ratón, el botón continúe con el aspecto que tiene cuando hacemos hover. Si volvemos a hacer click, volverá a su aspecto inicial y el hover seguirá aplicándose del mismo modo de siempre. 

Conclusiones

Por supuesto no todas las propiedades pueden utilizar una transición, pero para eso tenemos una lista (bastante amplia, reconozcámoslo) de la W3C con las propiedades que pueden animarse. Igualmente, estas propiedades aún están en consolidación: aún están en modo de compatibilidad, por lo que deben ir con sus respectivos prefijos (podemos olvidarnos de esto si usamos Sass y Compass, el mixin +transition ya los incluye por sí mismo). 

Las transiciones son un gran avance en la separación de la capa de presentación y una característica ampliamente demandada desde hace años. Una herramienta visual que añade un toque dinámico y fluido, fácil de usar y con un gran potencial. 

 

Enlaces

Ejemplo en Codepen

Tabla de propiedades 

Documentación en Mozilla Developer Network