Perspectivas CSS

Establecer punto de fuga para perspectivas en CSS


Cuando trabajamos con 3D en CSS, en muchas ocasiones es necesario dotar a nuestro trabajo de perspectiva. Con la propiedad perspective de CSS podemos establecer un punto de fuga con una cierta distancia:

PropiedadesFormatoSignificado
perspectivenone | distancePunto de fuga para los elementos hijos.
perspective-origin50% 50% | posX posYPunto de origen de la perspectiva.

La propiedad perspective nos permite darle un determinado punto de fuga al elemento hijo de un contenedor (debemos utilizarlo desde el contenedor padre), y se le aplica una cierta distancia, por ejemplo 400px. Mediante la propiedad perspective-origin podemos cambiar el punto de origen de la perspectiva, y con backface-visibility, podemos ocultar la cara «trasera» de un elemento, como explicaremos más adelante.

La propiedad perspective

Por defecto, la propiedad perspective-origin tiene un valor de 50% 50%, pero podemos cambiar estos valores (eje x y eje y) que representan el desplazamiento del origen de la perspectiva desde el punto superior izquierda del contenedor de referencia.

Al margen de cantidades, por ejemplo, en píxeles, también podemos indicar o valores como top, bottom, left, right o center.

Veamos un pequeño ejemplo donde se puede ir disminuyendo y ampliando el valor de perspective para ver como influye:

.container {
  width: 150px;
  height: 150px;
  transform-style: preserve-3d;
  perspective-origin: 50% 50%;
  perspective: 400px;
  border: 3px solid #888;
}

.element {
  width: 100%;
  height: 100%;
  background: red;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotateY(0);
  }
  100% {
    transform: rotateY(360deg);
  }
}
<div class="container">
  <div class="element"></div>
</div>

Observa que el valor de perspective-origin es el valor que tiene por defecto. Puedes cambiarlo para observar como repercute en el ejemplo.

La propiedad backface-visibility

Es posible que cuando tengamos un espacio 3D con elementos HTML, perspectiva y transformaciones, queramos que el elemento gire y en un momento concreto se visualice la cara A de nuestro elemento (una imagen, un cubo, etc...) y cuando haya girado completamente se vea la cara B del elemento.

Por la forma en la que trabaja CSS, puede que eso no ocurra y se vea siempre la misma cara, ya que no estamos trabajando con objetos 3D reales. Para ello, podemos utilizar la propiedad backface-visibility.

PropiedadesFormatoSignificado
backface-visibilityvisible | hiddenOculta la cara posterior de un elemento 3D.

La propiedad backface-visibility puede tomar dos valores: visible, el valor por defecto, y hidden. Mientras que el primero es que muestra siempre las caras, el segundo es el que nos permitirá ocultarla cuando la cara trasera de un elemento se este mostrando al usuario.

Veamos como funciona:

.container {
  width: 180px;
  height: 180px;
  position: relative;
  animation: spin 2s linear infinite;
  transform-style: preserve-3d;
}

.container img {
  width: 100%;
  height: 100%;
  position: absolute;
}

@keyframes spin {
  0% {
    transform: rotateY(0);
  }
  100% {
    transform: rotateY(360deg);
  }
}
<div class="container">
  <img class="a-side" src="manzdev-a.gif" alt="A side">
  <img class="b-side" src="manzdev-b.png" alt="B side">
</div>

Si nos fijamos en este ejemplo, hemos creado dos imágenes dentro de un contenedor. Ambas están posicionadas de forma que estarán superpuestas y si les aplicamos una animación que rote el contenedor en 360 grados sobre el eje Y, podremos comprobar que siempre veremos la imagen B, la última de ellas puesto que es la que tiene preferencia porque es la última que aparece en el orden de HTML.

Si ahora le añadimos la propiedad backface-visibility a hidden en la imagen B, entonces el navegador la ocultará cuando detecte que se encuentra en la cara posterior, simulando el 3D real:

img.b-side {
  backface-visibility: hidden;
}

Observa que ahora el resultado sería el adecuado. Aquí tienes una demo donde puedes comprobar la diferencia:

.container {
  width: 180px;
  height: 180px;
  position: relative;
  animation: spin 2s linear infinite;
  transform-style: preserve-3d;
}

.container img {
  width: 100%;
  height: 100%;
  position: absolute;
}

img.b-side {
  backface-visibility: hidden;
}

@keyframes spin {
  0% {
    transform: rotateY(0);
  }
  100% {
    transform: rotateY(360deg);
  }
}
<div class="container">
  <img class="a-side" src="manzdev-a.gif" alt="A side">
  <img class="b-side" src="manzdev-b.png" alt="B side">
</div>

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev