Cómo crear un carrusel de imágenes 3D con HTML5, CSS y JavaScript

- Andrés Cruz - EN In english

Cómo crear un carrusel de imágenes 3D con HTML5, CSS y JavaScript

Los carruseles son elementos muy vistosos y prácticos para presentar múltiples imágenes o contenidos en un espacio reducido. Se han convertido en una pieza prácticamente fundamental en cualquier sitio web moderno: un buen carrusel de imágenes nunca pasa desapercibido. En esta entrada veremos cómo crear un carrusel 3D con HTML5, CSS y JavaScript, como el siguiente:

Se trata de un tipo de slider o carrusel bastante inusual: tiene componentes 3D, rota sobre su propio eje y tiene un aspecto muy cuidado. Además, puedes variar su velocidad, pausarlo fácilmente y personalizarlo con los colores o imágenes que necesites.

Veremos un par de variaciones más para ejemplificar la versatilidad del código presentado, empleando las Animaciones en CSS y JavaScript. Crearemos un carrusel con paneles y otro con cartas animadas.

Definiendo la perspectiva para darle profundidad 3D al carrusel

Como explicamos en una entrada anterior sobre ENTENDIENDO LA PROPIEDAD PERSPECTIVE (PERSPECTIVA) EN CSS, esta propiedad permite variar la profundidad en el eje Z. Al colocar un perspective con un valor mayor a los 1000 píxeles conseguimos que el carrusel se perciba más grande y con mayor sensación de profundidad.

<style>
        .container {
            perspective: 1100px;
        }
</style>
<section class="container">
     <!-- Demás HTML para el carrusel -items 3D -->
</section>

Definimos también algo más de CSS para darle estilo al contenedor: su posición, tamaño y un borde que servirá como marco visual para resaltar el ítem del carrusel que esté directamente de frente en cada momento:

    .container {
      width: 210px;
      height: 140px;
      position: relative;
      margin: 0 auto 40px;
      border: 1px solid #CCC;
      perspective: 1100px;
    }

Posicionando los ítems del carrusel en un espacio 3D

Dentro de nuestro .container crearemos otro elemento que permitirá que sus hijos (los ítems del carrusel) sean mostrados en un espacio 3D. Para ello se usa la propiedad transform-style con el valor preserve-3d. Sin esta propiedad, los elementos hijos se renderizarían como elementos planos (2D), ignorando por completo las transformaciones 3D aplicadas.

    #carousel {
      width: 100%;
      height: 100%;
      position: absolute;
              transform: translateZ( -288px );
              transform-style: preserve-3d;
              transition: transform 1s;
    }
  <section class="container">
    <div id="carousel" style="transform: translateZ(-288px) rotateY(-360deg);">
     <!-- Elementos hijos 3D -->
    </div>
  </section>

Para entender cómo influye esta propiedad en la construcción del escenario 3D, veamos cómo quedaría el carrusel si no estuviera aplicada la propiedad transform-style con el valor preserve-3d:

Como puedes ver, sin esa propiedad todos los ítems quedan solapados y el resultado es completamente inutilizable. No te preocupes, con unas pocas líneas de CSS lo solucionamos de forma muy sencilla.

HTML5: Definiendo los ítems del carrusel 3D

Ahora definimos cada uno de los ítems que forman parte de nuestro carrusel. El CSS es bastante básico: un tamaño de fuente grande, dimensiones que abarcan casi todo el contenedor padre y un borde para resaltar cada carta. Puedes personalizarlo tanto como quieras, aunque ten cuidado con márgenes y paddings para evitar que las cartas o ítems se descuadren o se solapen entre sí:

    #carousel figure {
      display: block;
      position: absolute;
      width: 80%;
      height: 80%;
      left: 10px;
      top: 10px;
      border: 2px solid rgba(   0, 0, 0, 0.8 );
      line-height: 116px;
      font-size: 80px;
      font-weight: bold;
      color: white;
      text-align: center;
      margin: 0;
    }

Debemos ubicar cada ítem del carrusel de manera que no se solapen, distribuyéndolos uniformemente en los 360 grados del eje Y. La fórmula es simple: dividir 360° entre el número de ítems. En este ejemplo con 9 ítems, cada uno se separa 40°. Tendrás tantas reglas :nth-child como ítems tenga tu carrusel:

 #carousel figure:nth-child(1) {
              transform: rotateY( 0deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(2) {
              transform: rotateY( 40deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(3) {
              transform: rotateY( 80deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(4) {
              transform: rotateY( 120deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(5) {
              transform: rotateY( 160deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(6) {
              transform: rotateY( 200deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(7) {
              transform: rotateY( 240deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(8) {
              transform: rotateY( 280deg ) translateZ( 288px );
    }
    #carousel figure:nth-child(9) {
              transform: rotateY( 320deg ) translateZ( 288px );
    }

Finalmente, el HTML completo del carrusel:

  <section class="container">
    <div id="carousel">
      <figure>1</figure>
      <figure>2</figure>
      <figure>3</figure>
      <figure>4</figure>
      <figure>5</figure>
      <figure>6</figure>
      <figure>7</figure>
      <figure>8</figure>
      <figure>9</figure>
    </div>
  </section>

HTML + CSS + JavaScript: Juntando todos los pasos y creando el carrusel 3D rotativo

Al combinar todo el CSS y HTML anterior obtenemos el siguiente resultado:

Infografía: Resumen visual de los pasos anteriores

Puedes ver todos los pasos resumidos en la siguiente infografía:

Infografía: ¿Cómo crear un carrusel 3D con CSS?

Como ves, el carrusel estático ya está en su lugar, pero le falta lo más importante: movimiento. Afortunadamente, con las Animaciones CSS podemos conseguirlo con muy pocas líneas de código.

Rotación del slider: Animando el carrusel automáticamente con CSS

Para que el carrusel rote de forma automática e infinita, empleamos la directiva @keyframes junto con la propiedad animation. Basta con aplicar las siguientes reglas al elemento #carousel:

    #carousel {
        animation: rotateInY 10s infinite linear;
    }
    @keyframes rotateInY {
	0%   { transform: translateZ(-288px) rotateY(0deg);   }
	100% { transform: translateZ(-288px) rotateY(360deg);    }
    }

El valor infinite hace que la animación se repita indefinidamente, mientras que linear garantiza una rotación constante y uniforme, sin aceleraciones ni frenadas. Puedes ajustar el tiempo (10s) para controlar la velocidad del giro.

Una variación interesante es alargar cada uno de los ítems para que parezcan paneles verticales en lugar de cartas:

Desplazando el carrusel manualmente con JavaScript

En este último experimento veremos cómo, con un poco de JavaScript asociado a un par de botones, podemos controlar la posición del carrusel de forma manual y desplazarnos por cada uno de sus ítems uno a uno. La clave está en calcular el ángulo de rotación acumulado (theta) y aplicarlo como transform al elemento #carousel:

    var init = function() {
      var carousel = document.getElementById('carousel'),
          navButtons = document.querySelectorAll('#navigation button'),
          panelCount = carousel.children.length,
          
          theta = 0,
          onNavButtonClick = function( event ){
            var increment = parseInt( event.target.getAttribute('data-increment') );
            theta += ( 360 / panelCount ) * increment;
            carousel.style.transform = 'translateZ( -288px ) rotateY(' + theta + 'deg)';
		console.log("theta: ",theta)
          };
      for (var i=0; i < 2; i++) {
        navButtons[i].addEventListener( 'click', onNavButtonClick, false);
      }
    };
    init();

El ángulo de rotación por paso se calcula dividiendo 360 entre el número total de paneles (panelCount). Cada vez que el usuario pulsa un botón, el carrusel rota exactamente lo necesario para mostrar el siguiente o anterior ítem de forma precisa:

¿Cómo crear un carrusel de imágenes con CSS? #Infografía

Resumen visual del proceso completo para crear el carrusel 3D con CSS:

Infografía: cómo crear un carrusel de imágenes con HTML5 y CSS

Variación: Carrusel animado con CSS y efecto de cartas

Carrusel animado con CSS y efecto de cartas

Esta variación usa las mismas bases de CSS 3D que ya aprendimos, pero aplicadas a un efecto de cartas apiladas que rotan de forma cíclica. Puede usarse para mostrar imágenes, iconos, textos destacados o cualquier otro contenido HTML.

Haremos uso de las transformaciones 3D de CSS, por lo que encontraremos propiedades como perspective, que permite especificar la perspectiva de un objeto en píxeles, y transform para realizar traslaciones y rotaciones en los distintos ejes. En este experimento concreto, toda la acción ocurre sobre el eje Y.

La estructura en HTML será la siguiente:

<figure class="icon-cards">
	<div class="icon-cards__content">
		<div class="icon-cards__item"></div>
		<div class="icon-cards__item"></div>
		<div class="icon-cards__item"></div>
	</div>
</figure>

Ahora definimos el CSS para el contenedor padre .icon-cards__content:

.icon-cards__content {
	position: absolute;
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;
	animation: carousel 10s infinite cubic-bezier(1, 0.015, 0.295, 1.225) forwards;
}

Como ves, definimos transform-style: preserve-3d para que todas las animaciones y transformaciones CSS especificadas más abajo se visualicen en un espacio tridimensional real.

La función cubic-bezier() en CSS permite especificar la velocidad y el ritmo de las animaciones a través de cuatro puntos que definen una curva de Bézier. Es una alternativa mucho más flexible a valores predefinidos como ease, linear o ease-in-out.

Ahora es el turno de definir el CSS base de nuestras cartas:

.icon-cards__item {
	position: absolute;
	top: 0;
	left: 0;
	width: 190px;
	height: 210px;
	border-radius: 6px;
}
.icon-cards__item:nth-child(1) {
	background: rgba(252, 192, 77, 0.9);
	transform: rotateY(0) translateZ(182px);
}
.icon-cards__item:nth-child(2) {
	background: rgba(49, 192, 204, 0.9);
	transform: rotateY(120deg) translateZ(182px);
}
.icon-cards__item:nth-child(3) {
	background: rgba(236, 233, 242, 0.9);
	transform: rotateY(240deg) translateZ(182px);
}

Nada del otro mundo: un CSS común para definir el tamaño base de las cartas, y reglas específicas con ayuda del selector :nth-child para variar el color de fondo y la posición de cada carta, distribuyéndolas cada 120° para que no se solapen.

Por último, la animación @keyframes que orquesta todo el movimiento:

@-webkit-keyframes carousel {
	0%,  17.5% {
		transform: translateZ(-182px) rotateY(0);
	}
	27.5%, 45% {
		transform: translateZ(-182px) rotateY(-120deg);
	}
	55%, 72.5% {
		transform: translateZ(-182px) rotateY(-240deg);
	}
	82.5%, 100% {
		transform: translateZ(-182px) rotateY(-360deg);
	}
}

La animación rota el contenedor en el eje Y en incrementos de -120deg (una carta a la vez), haciendo una pequeña pausa en cada posición gracias a que los porcentajes de los @keyframes se definen en pares (por ejemplo, 0%, 17.5%). Esto crea ese efecto de "paso a paso" tan característico de los carruseles de cartas.

Si te ha gustado trabajar con efectos CSS avanzados, te invito a leer cómo crear un efecto de texto neón con solo CSS.

Aprende paso a paso cómo crear un carrusel de imágenes 3D con HTML, CSS y JavaScript. Incluye carrusel automático con animaciones CSS, carrusel manual con botones y variantes con paneles y cartas. Con ejemplos y código listo para usar.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

Acepto recibir anuncios de interes sobre este Blog.