17

3D: Entendiendo el espacio tridimensional con CSS ... ¡sin complicaciones!

Julio J
jjyepez
46979

Nota inicial: La forma de manipular elementos que muestro en este tutorial es la forma que yo personalmente consideré más simple para entender el espacio en 3D del DOM, pero ten en cuenta que no es la única y puedes encontrar devs o tutoriales que te muestren maneras diferentes de hacer lo mismo. Dicho esto … empecemos.

I - LA TEORÍA

Primero: X y Y

Empezaremos por entender el espacio del navegador en 2D (de la forma sencilla).
Como se muestra en la figura a)

  • X se refiere a la posición horizontal, de izquierda a derecha, con la propiedad left de css
  • Y se refiere a la posición vertical, de arriba hacia abajo, con la propiedad top

(también pueden usarse las propiedades right y bottom pero para efectos de mantenerlo simple no las tomaremos en cuenta)

  • Si queremos mover un div hacia la izquierda usando la propiedad left, le restamos a X, si lo queremos mover haca la derecha, le sumamos a X … (normalmente en pixeles).
  • Si queremos mover un div hacia arriba usando la propiedad top, le restamos a Y, si lo queremos mover haca abajo, le sumamos a Y.

Lo importante hasta acá es comprender a qué nos referimos cuando hablamos de X y cuando hablamos de Y

Luego: Z

A partir de html5 y CSS3, podemos también mover los divs (o cualquier elemento) hacia adelante o hacia atrás en el documento (2D) cómo si éste fuera un espacio 3D.
Entonces, como se representa en la figura b)

  • Z se refiere a la posición, de adelante hacia atrás o viceversa.

Aún no sabemos con qué propiedad de css lo vamos a mover, pero si sabemos que:

  • Si queremos mover un div hacia atrás le restamos a Z, si lo queremos mover haca adelante, le sumamos a Z.

Hasta este punto, tendremos claro a que nos referiremos con X, Y y Z.

NOTA: Si no ha quedado 100% claro, lo mejor es parar, revisar de nuevo lo anterior, y asegurarnos de comprenderlo antes de seguir.
.

Ahora la rotación: en X, Y y Z

Mucha atención al eje que está en rojo (aquí es dónde la mayoría se rinde y abandona).
Tú no, porque ya sabes el secreto: El eje de rotación es la clave de todo


Como vemos en las figuras c), d) y e) …

  • La rotación en X nos permite rotar el elemento sobre un eje que va de izquierda a derecha.
  • La rotación en Y nos permite rotar el elemento sobre un eje que va de arriba hacia abajo.
  • La rotación en Z nos permite rotar el elemento sobre un eje que va de adelante hacia atrás.

(Acabo de ahorrarte muchas horas de ensayo y error, y muchos dolores de cabeza.
You’re welcome 🤓🤘 )

La rotación se hace en grados, desde 0° (ó 0 deg en inglés) que sería sin rotación, hasta 360° que sería un giro o rotación completa hasta la posición original (también pueden indicarse valores por fuera de este rango pero para mantenerlo simple no entraremos en ese detalle por ahora).

NOTA: De nuevo, asegurémonos de tener todo 100% claro hasta aquí antes de seguir.
.

II - PASEMOS AHORA A LA PRÁCTICA

El html

Usaremos sólo divs y css para nuestro código.

<divclass="cubo">
  <divclass="cara frente"   >F<div>
  <divclass="cara detras"   >B<div>
  <divclass="cara arriba"   >U<div>
  <divclass="cara abajo"    >D<div>
  <divclass="cara izquierda">L<div>
  <divclass="cara derecha"  >R<div>
<div>

Tenemos:

  • Un div con la clase de css cubo, que usaremos como contenedor y dentro del cual armaremos un cubo.
    (Al colocar todas las caras dentro de este div, podremos manipular todo el conjunto luego con sólo hacer referencia a la clase .cubo)
  • Seis divs internos que representarán las caras del cubo.
    (Le hemos asignado una clase común: cara, a todos estos divs)
    Asignamos también una clase única a cada uno de los divs internos: frente, detras, izquierda, derecha, arriba y abajo, para darles propiedades css individuales más adelante.
    .

Un poco más de teoría de CSS

El nuevo CSS3 incorporó (entre otras funciones): translate3d y rotate3d para desplazar y rotar los elementos en el espacio tridimencional del documento html:

translate3d (X, Y, Z)

Los parámetros X, Y y Z funcionan exactamente como vimos en la primera parte para desplazar los elementos hacia arriba, abajo, izquierda, derecha, adelante o atrás, según el valor que le demos a cada uno, y si este valor es positivo o negativo (-).

rotate3d (usarEjeX, usarEjeY, usarEjeZ, G)

Los parámetros usarEjeX, usarEjeY y usarEjeZ pueden tener 1 o 0, para indicar a CSS cuál o cuáles ejes deberá usar para rotar el elemento exactamente como vimos en la primera parte, con un ángulo de giro de G grados.

La propiedad transform: de css nos permite entonces, usar estas funciones (y otras más) para transformar la posición, la rotación, etc. de los elementos en el documento a partir de su situación inicial y el punto de origen que se usará como base para mover y rotar el div como se ve en la figura f).

Ahora los estilos que usaremos
(Presta especial atención a los valores de las propiedades relacionadas con transform)

Fíjate que no está movido ni hacia adelante o atrás, izquierda o derecha, etc. ni rotado en nigún eje.
.

Finalmente 3D

Como ya habrás deducido, lo que tenemos que hacer entonces, es desplazar y rotar cada div de cada una de las caras, hasta el lugar correcto en el espacio tridimencional del documento para formar un cubo perfecto.

Tomando en cuenta que cada cara es un div de forma cuadrada donde cada uno de sus lados tiene el tamaño indicado en la variable @lado.

IMPORTANTE: Todos los divs (todos) deben tener position:absolute; … y el div contenedor debe tener obligatoriamente la propiedad transform-style con el valor preserve-3d … para que todo funcione correctamente, de lo contrarió no funcionará. (hay más teoría que puedes investigar sobre eso luego)

Esta es la versión resumida del CSS
Sólo muestra las propiedades más importantes relacionadas con 3D.

/* ---------------------------------------------
   NOTA: este código está hecho en LESS únicamente para usar la variable @lado
   y que se aprecie claramente su relación con la posición de las caras del cubo más abajo
  ---------------------------------------------- */@lado:20vw; /* --- no te compliques mucho con esto, es sólo una variable --- */.cubo{
  position: absolute;
  width : @lado;
  height: @lado;
  transform-origin: 50%50%;
  transform-style : preserve-3d;
}
/* propiedades comunes a todas las caras */.cara {
  position: absolute;
  width : @lado;
  height: @lado;
  transform-origin: 50%50%;
}
/* propiedades específicas para cada una de las caras del cubo */.cara.frente   {transform: translate3d(0,0, @lado/2)   rotate3d(0,0,0,0deg) }
.cara.detras   {transform: translate3d(0,0,-@lado/2)   rotate3d(0,0,0,0deg) }

.cara.izquierda{transform: translate3d( @lado/2,0,0)   rotate3d(0,1,0,90deg) }
.cara.derecha  {transform: translate3d(-@lado/2,0,0)   rotate3d(0,1,0,90deg) }

.cara.abajo    {transform: translate3d(0, @lado/2,0)   rotate3d(1,0,0,90deg) }
.cara.arriba   {transform: translate3d(0,-@lado/2,0)   rotate3d(1,0,0,90deg) }

A estas alturas ya tendrás bastante claro entonces, cómo funciona el espacio tridimencional del DOM con CSS.

Si es así, has hecho un excelente siguiendo este tutorial. ¡FELICITACIONES!
.

Si no, pues no pasa nada, te explico el detalle de los transforms de cada una de las caras del cubo:

Para la cara del frente sólo desplazamos hacia adelante (Z) el div la mitad de la distancia del @lado, sin darle ninguna rotación.
Para la cara de atrás sólo desplazamos hacia atrás (-Z) el div la mitad de la distancia del @lado, sin darle ninguna rotación.

.cara.frente   {transform: translate3d(0,0, @lado/2)   rotate3d(0,0,0,0deg) }
.cara.detras   {transform: translate3d(0,0,-@lado/2)   rotate3d(0,0,0,0deg) }

Desplazamos siempre las caras a una distancia equivalente a la mitad del @lado para que todo quede siempre ubicado correctamente con respecto al centro del espacio tridimencional.

Para la cara izquierda sólo desplazamos el div hacia la izquierda (-X) la mitad de la distancia del @lado, y lo rotamos 90 grados en Y para que quede en la posición correcta.
Para la cara derecha sólo desplazamos el div hacia la derecha (X) la mitad de la distancia del @lado, y lo rotamos también 90 grados en Y.

.cara.izquierda{transform: translate3d(-@lado/2,0,0)   rotate3d(0,1,0,90deg) }
.cara.derecha  {transform: translate3d( @lado/2,0,0)   rotate3d(0,1,0,90deg) }

Para la cara de abajo sólo desplazamos el div hacia abajo (Y) la mitad de la distancia del @lado, y lo rotamos 90 grados en X para que quede en la posición correcta.
Para la cara de arriba sólo desplazamos el div hacia arriba (-Y) la mitad de la distancia del @lado, y lo rotamos también 90 grados en X.

.cara.abajo    {transform: translate3d(0, @lado/2,0)   rotate3d(1,0,0,90deg) }
.cara.arriba   {transform: translate3d(0,-@lado/2,0)   rotate3d(1,0,0,90deg) }

… y LISTO!

Este es el CSS final
Sin LESS y con los estilos para la animación, las letras de cada cara del cubo y centrando todo en el documento para que se vea todo perfecto!

body{perspective:500px;height:90vh;}

div{box-sizing: border-box}

.cubo{
  position:absolute;
  width :20vw;
  height:20vw;
  transform-style: preserve-3d;
  transform-origin: 50%50%;
  top:50%; left:50%;
  margin-top: -10vw;
  margin-left: -10vw;
  animation: rotar3d 25s linear infinite;
  line-height: 20vw;
  font-size: 10vw;
}
.cara {
  position: absolute;
  color: rgba(0,0,0,.15);
  text-align:center;
  border:2px solid rgba(0,0,0,.25);
  width :20vw;
  height:20vw;
  transform-origin: 50%50%;
}
.cara.frente   {transform: translate3d(0,0, 10vw)   rotate3d(0,0,0,0deg) }
.cara.detras   {transform: translate3d(0,0,-10vw)   rotate3d(0,0,0,0deg) }
.cara.izquierda{transform: translate3d(-10vw,0,0)   rotate3d(0,1,0,90deg) }
.cara.derecha  {transform: translate3d( 10vw,0,0)   rotate3d(0,1,0,90deg) }
.cara.abajo    {transform: translate3d(0, 10vw,0)   rotate3d(1,0,0,90deg) }
.cara.arriba   {transform: translate3d(0,-10vw,0)   rotate3d(1,0,0,90deg) }

@key frames rotar3d{
  from{transform: rotate3d(0,0,0,0)}
  to  {transform: rotate3d(1,1,1,360deg)}
}

Resultado

Puedes ver el código real funcionando en este link de Codepen.io

Espero que les haya gustado el tutorial, que llevó algunas horas … fuiuu! … pero creo que valió la pena … a mí me gustó como quedó.
CSS es todo un mundo! Ánimate a llegar más lejos … ¡Adelante!

Deja tus comentarios abajo y dale a la manito en el título si te ha gustado este tutorial. bai!

Julio J.

Escribe tu comentario
+ 2