Transiciones en CSS-3 (transition)

Transiciones CSS3 La especificación CSS3 Transitions en fase WC del 3 de Abril de 2012 contempla las transiciones de las propiedades de estilo. Esa especificación está en fase de borrador, por lo que puede sufrir cambios y su implementación puede diferir de un navegador a otro. Con las transiciones se consigue que el cambio en una propiedad de estilo ocurra de forma gradual o suave durante un tiempo determinado. Por ejemplo, si desde JavaScript modificamos el ancho y alto de un elemento, esto ocurre de forma inmediata. Con transiciones este cambio será gradual, en un grado que puede ser configurado.

Ejemplo:

Sin transiciónCon transición
 
 
Los ejemplos de esta página se prueban en Chrome 18.0, Safari 5.1, Firefox 12.0 y Opera 11.64. Tener en cuenta que las características que no funcionan según lo esperado para una determinada versión es posible que si lo haga en versiones posteriores de esos navegadores cuando esté leyendo este tema.

El primer elemento tiene estilo incorporado en línea, es decir, dentro del atributo style:

<div id="box1" style="
width: 50px;
height: 50px;
background-color: olive;
display: inline-block;
">&nbsp;</div>

Siempre es preferible incluir el estilo en el elemento <style> de la página o mejor en un archivo externo. Pero para estos ejemplos lo pondré en línea para que pueda, en su caso, consultarlo en el código fuente. Pues bien, ese estilo dota unas dimensiones al elemento. Luego con el botón lo que hacemos es cambiarle esas dimensiones. Para el segundo elemento tenemos:

<div id="box2" 
data-vpforcss="transition"
style="
transition: width 1s ease-in-out, height 1s ease-in-out;                       
width: 50px;
height: 50px;
background-color: olive;
display: inline-block;
"> </div>

Antes dije que el estilo era preferible no ponerlo en línea, a excepción de las nuevas propiedades de CSS3 que pueden ser objeto de que se necesiten prefijar. Es lo que se conoce como los vendor prefixes o prefijos propietarios de CSS. En este caso estoy usando el gestor vpForCss de vendor prefixes para CSS3, donde se requiere que el estilo de las propiedades a prefijar esté en línea y, además, agregar un atributo data-vpforcss.

Resumen de vpForCSS: Tenemos que escribir la/s propiedad/es sin prefijo, pues vpForCss se encarga de dotar del prefijo adecuado a cada navegador. Hemos de incluir un atributo data-vpforcss con una lista de propiedades que vayamos a dotar específicamente para ese elemento, así como incluir en el window.onload todas las que vayamos a usar en esta página:
window.onload = function(){
    prefijarCss(["transition", "transition-property", 
        "transition-duration", ...]);
    dotarVpCss();
}
Hay que vincular esas dos funciones prefijarCss() y dotarVpCss() que encontrará en la documentación señalada, por ejemplo, usando el script vpforcss.js. O bien en otro caso si no desea usar un gestor o preprocesador de prefijos, debe explicitar todos los prefijos:
-webkit-transition: width 1s ease-in-out, height 1s ease-in-out; 
-moz-transition: width 1s ease-in-out, height 1s ease-in-out;
-ms-transition: width 1s ease-in-out, height 1s ease-in-out; 
-o-transition: width 1s ease-in-out, height 1s ease-in-out; 
... etcétera...            
transition: width 1s ease-in-out, height 1s ease-in-out;
Pues a fecha de hoy los navegadores actuales no soportan esta propiedad sin prefijo.

La propiedad transition usada antes se declara de forma resumida, o shorthand como dice la especificación. Pero realmente se compone de cuatro sub-propiedades: transition-property, transition-duration, transition-timing-function y transition-delay. Cada subpropiedad admite una lista de valores, como en este ejemplo:

Ejemplo:

 
click para mover

El estilo significativo para el contenedor exterior con borde azul y el cuadro con fondo azul es este, omitiendo lo innecesario para el tema (el resto lo puede consultar en el código fuente de esta página):

<div style="..."
onclick="transBox3(this, this.firstChild)"
><div id="box3"
    data-vpforcss = "transition-property, transition-duration"
    style="
    ...
    left: 0px;
    opacity: 1;
    transition-property: opacity, left;
    transition-duration: 2s, 4s;"
    >&nbsp;</div>
    click para mover
</div>
...
<script>
    function transBox3(diver, box){
        box.style[vpForCss["transition-duration"]] = 
            document.getElementById("box3-dopacity").value + "s, " +
            document.getElementById("box3-dleft").value + "s";
        if (box.style.left == "0px") {
            box.style.left = (diver.offsetWidth - box.offsetWidth) + "px";
            box.style.opacity = "0.25";
        } else {
            box.style.left = "0px";
            box.style.opacity = "1";
        }
    }
</script>

Aparte de otras propiedades necesarias para configurar el efecto, las resaltadas en amarillo son las que intervienen en la transición. La posición izquierda con left pasa de 0 al ancho del contenedor menos el ancho del elemento. La opacidad transiciona entre 1 y 0.25. Pero ésta lo hace con una duración de 2 segundos mientras que la posición lo hace en 4 segundos. Así que la opacidad llega al valor final antes que la posición. Puede experimentar con otros valores.

En el caso de que la lista de valores no coincida en longitud, la longitud de la lista de la sub-propiedad transition-property determina el número de entradas de la lista. Por ejemplo:

div {
    transition-property: opacity, left, top, width;
    transition-duration: 2s, 1s;
  }

La lista de transition-property tiene cuatro entradas mientras que la de transition-duration tiene dos. Así se aplica la segunda lista de forma iterada tantas veces como necesite la primera lista. En este ejemplo aplicará sucesivamente 2s, 1s para opacity, left respectivamente y nuevamente 2s, 1s para top, width. Si la segunda tiene más términos que los que necesita la primera, el resto se ignora.

La propiedad de la transición (transition-property)

Con la propiedad transition-property declaramos el nombre de la propiedad CSS sobre la que se aplica la transición. Los valores posibles son:

none | [ all | ‹IDENT› ] [ ',' [ all | ‹IDENT› ] ]*

Traducido como sigue:

  • Un valor none
  • O bien una o más declaraciones separadas por comas de
    • Un valor all
    • O bien un nombre de propiedad (IDENT)

Con none desactivamos las transiciones. El valor inicial es all, por lo que transiciona todas las propiedades. Realmente la especificación expone ‹IDENT› que viene a ser una identidad, que se corresponde con el nombre de una propiedad. Aunque hay algunas lagunas aún al respecto, por ejemplo ¿se puede permitir inherit como un valor ‹IDENT›?

Tipos de animaciones de propiedades de transición

Las propiedades que pueden usarse para transiciones deben tener la capacidad de ser animadas. Se establece una característica que afecta a todas las propiedades CSS que se denomina animatable (¿Se traduce como capaz de ser animado?), indicando el tipo de animación que se le ha de aplicar. Algunos tipos de animación son color, length, percentage, integer, rectangle, visibility, etc. Cada tipo tiene un comportamiento, así por ejemplo la propiedad background-color tiene el tipo color. Algunas propiedades pueden tener varios tipos, como font-size a la que se pueden aplicar los tipos length y percentage. Este ejemplo servirá para ver el comportamiento de cada tipo de animación.

Ejemplo:

Ejemplos de tipos de animación

Tipo de animación:
Valores:  
Aplica a:  
Ejemplo con:  
Valor inicial:  
Valor final:  
Esto es una capa con z-index:5 y opacidad 0.5 situada entre el contenedor del fondo y el elemento de prueba situado inicialmente en z-index:10. Sirve para probar el tipo integer con la propiedad z-index.
TEXTO
Estilo del elemento:  
Este ejemplo ha funcionado como se esperaba para Chrome 18.0, Safari 5.1, Firefox 12.0 y Opera 11.64, este con algunos tipos de animación que no resultan como los otros dos.

En el ejemplo anterior, cuyos datos se han obtenido de la especificación en fase de borrador que mencioné más arriba, figuran otros tipos de animaciones que no he usado, como transform list o gradient, pues aún no he practicado con estos estilos de CSS3. En la especificación encontrará una tabla completa con todas las propiedades que se pueden animar, por lo que no voy a repetirla aquí. Esa especificación dice también que algunas propiedades no se han incluido pero ya funcionan en algunos navegadores y es posible que se incluyan. Son background-size, border-*-radius, box-shadow, column-count, column-gap, column-rule-color, column-rule-width, column-width, font-size-adjust, font-stretch, marker-offset, text-decoration-color, transform, transform-origin.

La duración de la transición (transition-duration)

Con transition-duration declaramos la duración de la transición. Toma los valores:

‹time› [, ‹time›]* 

En mi glosario XHTML 1.0 + CSS2.1 expuse lo relacionado con los valores usados en CSS. Esa información habría que actualizarla con nuevos tipos de valores de CSS3, declarados en la especificación Valores y unidades en CSS3. Ahí también encontramos la definición de la sintaxis usada en todas la especificaciones de CSS3 (en todos los módulos) para definir como se escriben los valores de las propiedades. Así un palabra clave (keyword) se escribiría literalmente, por ejemplo auto o none, mientras que un tipo básico de datos (basic data type) se escribe entre paréntesis angulares como ‹time›. Esto no es un elemento HTML, sino un tipo básico de datos de CSS. En estos temas usaré los caracteres ‹ › (&lsaquo; &rsaquo;) en lugar de < > (&lt; &gt;) para evitar confusiones.

El tipo básico de datos ‹time› se puede referir a segundos (p.e. 2s) o milisegundos (p.e. 2ms). Son a su vez del tipo dimension, que es un número inmediatamente seguido de un identificador de unidad, por ejemplo 15px o 3cm.

La función de temporización de la transición (transition-timing-function)

La propiedad transition-timing-function describe cómo se calculan los valores intermedios durante la transición. Los valores posibles son:

[ ease | linear | ease-in | ease-out | ease-in-out |
step-start | step-end | steps(‹integer›[, [ start | end ] ]?) |
cubic-bezier(‹number›, ‹number›, ‹number›, ‹number›) ]
[, [ ease | linear | ease-in | ease-out | ease-in-out | step-start |
step-end | steps(‹number›[, [ start | end ] ]?) |
cubic-bezier(‹number›, ‹number›, ‹number›, ‹number›) ] ]* 

Todo eso podríamos expresarlo así:

  • Puede contener uno o más valores separados por comas entre los siguientes
    • Un valor de transición de tipo ease entre los siguientes:
      • ease
      • ease-in
      • ease-out
      • ease-in-out
    • O un valor linear
    • O un valor de transición de tipo step entre los siguientes:
      • step-start
      • step-end
      • steps(‹integer›[, [ start | end ] ]?)
    • O una función de curva cúbica Bézier con cubic-bezier(‹number›, ‹number›, ‹number›, ‹number›)

En el siguiente ejemplo probamos valores:

Ejemplo:

timing-function

steps(, )
cubic-bezier(, , , )
2s ease
  • Menú uno
  • Otro menú
  • Tercero
Estilo del primer elemento (los otros son iguales)
 

Este ejemplo usa una lista con elementos <li> sobre los que aplicamos distintos valores de transition-timing-function para observar el comportamiento. El HTML es el siguiente:

<ul>
    <li data-vpforcss="transition-property, transition-duration,
    transition-timing-function"
    class="trans-menu"
    style="transition-property: width, color, background-color;
           transition-duration: 2s;
           transition-timing-function: ease;"
    >Menú uno</li>    
    ...Los demás son iguales...
</ul>

Cada entrada de lista tiene el atributo data-vpforcss para activar el gestor de vpForCss y no tener que estar escribiendo prefijos para cada navegador. Esto, como ya dije más arriba, requiere que el estilo se declare en el atributo, dentro del elemento. El resto del estilo lo encontramos en el <head> de esta página:

li.trans-menu {
    list-style-type: none;
    margin-left: -2em;
    padding: 0.2em;
    font-family: Arial Black;
    cursor: pointer;
    width: 6em;
    color: yellow;
    background-color: rgb(0,0,75);
}
li.trans-menu:hover {
    width: 10em;
    color: lime;
    background-color: rgb(0,0,255);
}

Las propiedades a transicionar están en color azul. El evento CSS hover actúa al señalar un elemento, por lo que es adecuado para activar y desactivar una transición. Poco más hay que decir, sino ir probando los valores para ver su comportamiento y aprender que significan. Algunos valores como step-end pueden dar la impresión de que no funcionan si no le damos el tiempo de la duración de la transición hasta que actúe.

La demora de la transición (transition-delay)

Con transition-delay definimos en tiempo cuando empezará a actuar la transición. Un valor de 0s significa que se ejecutará tan pronto como la propiedad sea cambiada. En otro caso la ejecución de la transición se demora en empezar esa cantidad de tiempo. También admite valores negativos, de tal forma que al inicio parecerá que ya lleva un tiempo ejecutada. El valor es igual que para transition-duration:

‹time› [, ‹time›]* 

La propiedad resumida transition

La propiedad resumida o shorthand transition combina las cuatro propiedades:

[‹'transition-property'› || ‹'transition-duration'› || 
‹'transition-timing-function'› || ‹'transition-delay'›
[, [‹'transition-property'› || ‹'transition-duration'› ||
‹'transition-timing-function'› || ‹'transition-delay'›]]*

En las especificaciones de CSS cuando encontramos ‹'propiedad'› significa que son valores que se obtienen de esa propiedad. El orden de aparición no es importante, aunque si aparecen dos valores de tiempo, el primero se aplicará a transition-duration y el segundo a transition-delay.


Y hasta aquí lo básico para tener una idea general acerca de las transiciones, suficiente para empezar a hacer cosas.