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)
(también pueden usarse las propiedades right y bottom pero para efectos de mantenerlo simple no las tomaremos en cuenta)
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)
Aún no sabemos con qué propiedad de css lo vamos a mover, pero si sabemos que:
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) …
(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 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.