Wextensible

Traslación (translate)

Transformaciones con CSS3 Las transformaciones en CSS-3 nos permiten aplicar efectos sobre los elementos como traslación, rotación, escalado e inclinado. La especificación en fase WD CSS3 Transforms reúne transformaciones 2D y 3D, es decir, para espacios de dos y tres dimensiones. En este tema expondré una introducción sólo a la transformaciones 2D con ejemplos comentados.

En este primer ejemplo podemos ver una traslación.

Ejemplo:

<div class="lienzo">
    <div class="muestra"></div>
    <div class="muestra" data-muestra-prefijo></div>
</div>
<!-- LO QUE SIGUE ESTÁ EN EL HEAD DEL DOCUMENTO -->
<style>
    /* Contenedor base para todos los ejemplos */
    div.lienzo {
        position: relative;
        width: 300px;
        height: 200px;
        outline: blue solid 1px;
        overflow: hidden;
    }

    /* Código base para un contenedor de muestra de distintos ejemplos */
    div.muestra {
        position: absolute;
        left: 0px;
        top: 0px;
        width: 100px;
        height: 100px;
        background-color: rgba(255,0,0,0.2);
        font-size: 2em;
    }

    /* Ejemplo traslación */
    div[data-muestra-prefijo] {
        background-color: rgba(0,255,0,0.2);
        /* Chrome 23 y Safari 5.1,17 aún necesitan prefijo. Opera 12.11 y
           Firefox 17 ya no necesitan prefijo. Opera también lee el
           prefijo webkit */
        -webkit-transform: translate(50px, 50px);
        -moz-transform: translate(50px, 50px);
        -o-transform: translate(50px, 50px);
        transform: translate(50px, 50px);
    }
</style>

El contenedor class="lienzo" (con borde azul) nos sirve de base para meter los elementos sobre los que haremos pruebas. Tiene un posicionamiento relativo porque luego le pondremos uno absoluto a los elementos que vamos a transformar, pues queremos ver en pantalla exactamente la nueva posición que ocupan sin que pueda ser modificada por el flujo del documento. Los ejes graduados que aparecen en la imagen no están en este código porque los incorporo con JavaScript y nada tienen que ver con este tema. Si desea verlo puede consultar el archivo ejes.js entre los vinculados a este documento. Use el botón "Código" de la barra superior para ver el código fuente original.

El contenedor con class="muestra" contiene el estilo básico para diversos elementos. Puede ver el contenedor con color rojo con transparencia ubicado a 0 píxeles de los bordes y con medidas de 100 píxeles. Otro contenedor de color verde con transparencia tiene el mismo estilo class="muestra" y también un atributo data-muestra-prefijo que nos servirá para dotar del estilo para la transformación. Esto se consigue con transform: translate(50px, 50px). Este contenedor traslada su posición en la esquina superior izquierda en (0, 0) a la posición (50, 50). Las versiones actuales de Firefox 17 y Opera 12.11 admiten esta propiedad sin prefijar. Pero Chrome 23 y Safari 5.1.7 aún necesitan el prefijo -webkit-.

En relación con los prefijos CSS en este sitio ya he implementado una solución para no tener que estar escribiéndolos. En el tema Gestor vpForCss encontrará más detalles acerca de esto. El siguiente ejemplo es igual que el anterior haciendo uso de ese gestor de prefijos:

Ejemplo:

<div class="lienzo">
    <div class="muestra"></div>
    <div class="muestra" data-muestra
         data-vpforcss="transform"
         style="transform: translate(50px, 50px);
         background-color: rgba(0,255,0,0.2);
         "></div>
</div>

En el window.onload cargamos el código de un script general.js que nos permite hacer prefijarCss(["transform", "transform-origin"]) para declarar que vamos a usar esas dos propiedades CSS en la página. A continuación haciendo dotarVpCss() buscamos todos los elementos que tengan un atributo data-vpforcss con una lista de propiedades y cambiamos el estilo en línea de, por ejemplo, transform por -webkit-transform en el caso de Chrome. El único inconveniente es que hemos de poner el estilo en línea, pero aún así nos evitamos tener que escribir prefijos. En el resto de ejemplos de esta página usaré este gestor de prefijos.

Rotación, escalado y ejes de la transformación (rotate, scale)

Otras transformaciones son la rotación y el escalado. En este ejemplo veremos paso a paso como realizamos transformaciones teniendo en cuenta los ejes de la transformación. Una transformación siempre se aplica sobre un sistema de coordenadas, en nuestro caso los ejes X e Y. En cada elemento se establecen estos ejes siendo el punto de origen (0, 0) el vértice superior izquierda. El eje X crece hacia la derecha y el eje Y crece hacia abajo. Es importante entender que el eje de coordenadas sobre el que se aplica la transformación es el del propio elemento, no el del contenedor padre ni ningún otro. Una simple traslación no modifica esos ejes pero si lo hace la rotación y el escalado.

Ejemplo:

1
2
3
4
5
6
<div class="muestra" id="muestra1">1</div>
<div class="muestra" id="muestra2"
     data-vpforcss="transform"
     style="transform: translate(50px, 50px);">2</div>
<div class="muestra" id="muestra3"
     data-vpforcss="transform"
     style="transform: translate(50px, 50px)
                       rotate(45deg);">3</div>
<div class="muestra" id="muestra4"
     data-vpforcss="transform"
     style="transform: translate(50px, 50px)
                       rotate(45deg)
                       scale(0.5,0.5);">4</div>
<div class="muestra" id="muestra5"
     data-vpforcss="transform"
     style="transform: translate(50px, 50px)
                       rotate(45deg)
                       scale(0.5, 0.5)
                       translate(250px, 0px)">5</div>
<div class="muestra" id="muestra6"
     data-vpforcss="transform"
     style="transform: translate(50px, 50px)
                       rotate(45deg)
                       scale(0.5, 0.5)
                       rotate(-45deg)
                       translate(250px, 0px)
                       rotate(45deg);">6</div>
</div>

Veámos este ejemplo paso a paso que muestra como las transformaciones de rotación y escalado se van acumulando modificando los ejes de coordenadas del elemento. Tenemos 6 contenedores en principio todos con display: none. A medida que avanzamos pasos se van mostrando. En cada uno de ellos ponemos el mismo estilo de tranformación que tenía el anterior y agregamos una nueva para ir viendo el proceso. Le vamos cambiando el color y le ponemos un número para diferenciarlos.

  1. Un contenedor de color rojo con transparencia a (0, 0) píxeles del contenedor padre y con dimensiones 100×100 píxeles. El origen de coordenadas es su vértice superior izquierda que sirve de referencia también para, por ejemplo, posicionarlo con left y top.
  2. Traslación con transform: translate(50px, 50px) ubica un nuevo contenedor verde con su esquina superior izquierda en la posición (50, 50). Se traslada 50px desde el origen de coordenadas de ese elemento que previamente estaba ubicado en (0, 0). Los ejes siguen estando en su estado normal, con el origen ubicado en el vértice superior izquierda del elemento trasladado.
  3. Rotación con rotate(45deg) hace que gire 45 grados en dirección de las agujas del reloj. El origen de coordenadas (50, 50) se traslada provisionalmente y de forma automática al centro geométrico del elemento, el punto (100, 100). Entonces se gira y luego se vuelve a reponer el origen en el que ahora está girado, es decir, en el vértice superior del rombo (número 3) que aparece en pantalla. Ahora los ejes X,Y para este elemento cruzan este punto y por tanto están rotados 45 grados.
  4. Escalado con scale(0.5, 0.5) hace que reduzca su tamaño a la mitad en ambas direcciones X,Y. También con el escalado se traslada el origen al centro geométrico, se escala y luego se vuelve a reponer el origen en su lugar: el vértice superior del rombo de color azul (número 4).
  5. Si ahora hacemos translate(250px, 0px) se realiza una traslación de 250px en el eje X, pero previamente hemos rotado y luego escalando a 0.5, lo que resultará en 125px siguiendo la dirección de los ejes rotados. Si medimos en pantalla la distancia entre los dos vértices superiores izquierda de los rombos azules 4 y 5 y luego comprobamos esa distancia en el eje graduado verá que son exactamente 125px. El elemento se sale del contenedor y se recorta porque le hemos puesto overflow: hidden.
  6. Para trasladarlo horizontalmente con respecto a la página hemos de retroceder la rotación con rotate(-45deg), quedando los ejes X,Y en posición normal, luego aplicar la traslación con translate(250px, 0px) y finalmente lo volvemos a rotar rotate(45deg). Se ubicará a 125px del número 4 pues en un paso anterior ya lo habíamos escalado.

El origen de la transformación (transform-origin)

Antes vimos como los ejes se modifican con las rotaciones y escalados. La propiedad transform-origin nos permite reubicar el origen de la transformación. O dicho de otra forma, ubicar el origen de coordenadas en cualquier punto. Estos ejemplos nos ayudarán a entenderlo.

Ejemplo:

transform: rotate



transform-origin: 50px 50px

Código completo de este ejemplo

En el código del CSS no incorporamos ningún estilo para transformaciones. Lo hacemos en el script. El botón rotar responde con una función que incrementa el ángulo en tramos de 10 grados. Luego se inserta el estilo muestraRotar.style.transform = "rotate(" + angulo + "deg)". Aunque realmente lo hacemos mediante el uso del gestor de prefijos vpForCss con muestraRotar.style[wxG.vpForCss["transform"]]. Aquí wxG es una referencia al módulo general.js donde se encuentra el array vpForCss que contiene la propiedad transform con el prefijo adecuado para el navegador donde se está ejecutando. Pero aparte de este gestor de prefijos, lo que realmente estamos haciendo es ...style.tranform = "rotate(...)" sin más.

Al selector de opciones le hemos puesto una función para modificar el origen de la transformación. A efectos de visualizar el punto donde queremos rotar, ubicamos un elemento puntoRotar en una posición determinada que nos viene en los atributos data-left y data-top de las opciones. El atributo value porta la cadena de estilo para transform-origin:

PuntoPosición del punto respecto
del contenedor exterior
Origen de transformación
respecto del elemento
Centro(100, 100)(50, 50)
Superior izquierda(50, 50)(0, 0)
Superior derecha(100,100)(100, 0)
Inferior izquierda(100,100)(0, 100)
Inferior derecha(100,100)(100, 100)
Punto externo(200,100)(150, 50)

Luego aplicamos el estilo muestraRotar.style.transformOrigin = "50px 50px" por ejemplo para rotar con respecto al centro del elemento. El origen puede situarse en cualquier punto incluso externo al elemento, pero siempre teniendo en cuenta que las dimensiones son referidas al punto (0, 0) del elemento, esquina superior izquierda del mismo.

También podemos aplicar lo mismo a una transformación de escalado:

Ejemplo:

transform: scale


transform-origin: 50px 50px

Código completo de este ejemplo

Líneas oblicuas con HTML y CSS usando transformaciones

Si tenemos que situar una línea oblicua en un elemento HTML sin CSS tendríamos que usar SVG o un elemento canvas. Pero con las transformaciones CSS es fácil dibujar líneas oblicuas.

Ejemplo:

<div class="lienzo">
    <div class="linea" data-linea1></div>
    <div class="linea" data-linea2
         data-vpforcss="transform, transform-origin"
         style="transform-origin: 0px 0px;
                transform: rotate(45deg)"></div>
</div>

<!-- Esto está en el head del documento -->
<style>
    /* Ejemplo de líneas oblicuas con HTML y CSS */
    div.linea {
        position: absolute;
        left: 50px;
        top: 25px;
        height: 10px;
        width: 200px;
    }
    [data-linea1] {
        border-top: blue solid 3px;
    }
    [data-linea2] {
        border-top: red solid 3px;
    }

</style>

Las dos líneas son de la clase class="linea" dotándolas de posicionamiento absoluto. El alto no es significativo pero si el ancho de 200px. El atributo data-linea1 y data-linea2 da estilo a la línea azul y roja respectivamente, dibujando sólo el borde superior. El estilo, que incorporamos en línea, transforma la segunda recta desplazando su origen de transformación a su punto (0, 0). Luego la rotamos 45 grados y ya tenemos una recta oblicua con CSS.

La transformación de inclinado (skew)

La transformación de inclinado se consigue con transform = skewX(angulo), skewY(angulo) o skew(angulo1, angulo2) para aplicarla a los dos ejes. Poco más hay que decir pues viendo el ejemplo y el código es suficiente para entenderlo.

Ejemplo:

transform: skewY
transform: skewX
transform: skew
<div class="lienzo" data-sin-ejes>
    <div class="muestra-skew"
         data-vpforcss="transform"
         style="transform: skewY(10deg)"
    >transform: skewY</div>
    <div class="muestra-skew"
         data-vpforcss="transform"
         style="transform: skewX(10deg)"
    >transform: skewX</div>
    <div class="muestra-skew"
         data-vpforcss="transform"
         style="transform: skew(10deg, 10deg)"
    >transform: skew</div>
</div>

<!-- Esto está en el head del documento -->
<style>
    /* Ejemplo de transformación inclinada */
    div.muestra-skew {
        margin: 25px;
        border: red solid 2px;
        color: yellow;
        background-color: navy;
        text-align: center;
        font: bold 1.2em Arial;
        padding-top: 0.2em;
        padding-bottom: 0.2em;
    }
</style>

Y hasta aquí esta introducción a las transformaciones 2D de CSS-3. Queda por ver el tema de las matrices que se aplicaría con transform: matrix(n1, n2, n3, n4, n5, n6) para 2D. Y también todo lo relacionado con 3D donde hay otras transformaciones como perspective(longitud).