Slider al estilo de Apple con CSS3

¿Alguna vez habéis visto el Slider que utiliza Apple en su página web? ¿Os habéis preguntado cómo hacen ese efecto con los productos? Veamos como hacer un Slider parecido.

Antes de comenzar, podéis ver el resultado aquí. En este tutorial aprenderemos a hacer un Slider lo más parecido al de Apple posible, eso sí, no quedará igual, ya que ellos utilizan animaciones CSS3 y eso ocuparía demasiado código en mi opinión para escribirlo, así que lo nuestro será una versión más simple con transiciones. Sin más preámbulos, vamos allá.

index.html

Comenzamos con nuestro archivo principal. Sus contenidos serán los siguientes:

<div class="slider">
	<div class="slider__slides">
		<ul>
			<li><img src="thumb/ipodshuffle.jpg"><span>iPod Shuffle</span></li>
			<li><img src="thumb/ipodnano.jpg"><span>iPod Nano</span></li>
			<li><img src="thumb/ipodclassic.jpg"><span>iPod Classic</span></li>
			<li><img src="thumb/ipodtouch.jpg"><span>iPod Touch</span></li>
			<li><img src="thumb/appletv.jpg"><span>Apple TV</span></li>
			<li><img src="thumb/accessories.jpg"><span>Accesorios</span></li>
		</ul>
		<ul>
			<li><img src="thumb/itunes.jpg"><span>Descarga iTunes 10</span></li>
			<li><img src="thumb/giftcards.jpg"><span>Tarjetas Regalo de iTunes</span></li>
			<li><img src="thumb/nike.jpg"><span>Nike + iPod</span></li>
			<li><img src="thumb/red.jpg"><span>(PRODUCT) RED</span></li>
			<li><img src="thumb/headphones.jpg"><span>Auriculares de Tapón</span></li>
		</ul>
	</div>
	<div class="slider__caret"></div>
	<div class="slider__menu">
		<ul>
			<li><a>Productos</a></li>
			<li><a>iTunes y más</a></li>
		</ul>
	</div>
</div>

Veamos la descripción del cada elemento:

  • slider__slides: contendrá el contenido de cada sección, es decir, los productos. Cada lista en su interior representa una sección.
  • slider__caret: “triangulito” que representa nuestra posición actual.
  • slider__menu: menú con los nombres de las secciones.

La teoría

Las listas dentro de slider__slides estarán posicionadas como absolute, lo que significa que todas estarán una encima de las otras. Una vez en ese punto, posicionaremos todas a 3000px, lo que significará que no se verá ninguna.

Cuando apliquemos las clases .enter-left o .enter-right en los <li> irán posicionandose en la posicion x = 0px, a diferentes velocidades, dependiendo de la posición del elemento.

La clase .exit-left, posicionará el elemento a -3000px, por lo que más tarde podremos hacer que entre hacia el otro lado. En su defecto, .exit-right lo posicionará a 3000px, es decir, hacia la derecha.

Resumiendo, las clases exit determinarán hacia qué lado se esconde la lista. Las clases enter solamente cambiarán la velocidad en que se moverán los elementos, la cual debe ser opuesta dependiendo del lado del que entren.

Espero no haber complicado mucho el asunto. Veámoslo mejor siguiendo el tutorial, a continuación el código CSS.

style.css

Primero los estilos generales del Slider.

.slider {
	position: relative;
	overflow: hidden;
	margin: 100px auto;
	width: 950px;
	outline: 6px solid rgba(0, 0, 0, .02);
	border: 1px solid rgba(0, 0, 0, .08);
	background-color: #fff;
	color: #555;
	font-size: 11px;
	font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
}

	.slider ul {
		display: inline-block;
		margin: auto;
		padding: 0;
		width: auto;
		list-style: none;
	}

Ahora veamos las listas de productos:

.slider__slides {
	height: 190px;
}
	
	.slider__slides ul {
		margin-top: 15px;
	}

	.slider__slides img,
	.slider__slides span {
		display: block;
		margin: auto auto 10px;
	}

	.slider__slides li {
		float: left;
		width: 140px;
	}

	.slider__slides li {
		-webkit-transition: -webkit-transform 0.6s;
		-moz-transition: -moz-transform 0.6s;
		-ms-transition: -ms-transform 0.6s;
		-o-transition: -o-transform 0.6s;
		transition: transform 0.6s;
	}

	.slider__slides li.exit-left {
		-webkit-transform: translateX(-3000px);
		-moz-transform: translateX(-3000px);
		-ms-transform: translateX(-3000px);
		-o-transform: translateX(-3000px);
		transform: translateX(-3000px);
	}

	.slider__slides li,
	.slider__slides li.exit-right {
		-webkit-transform: translateX(3000px);
		-moz-transform: translateX(3000px);
		-ms-transform: translateX(3000px);
		-o-transform: translateX(3000px);
		transform: translateX(3000px);
	}

	.slider__slides li.enter-left,
	.slider__slides li.enter-right {
		-webkit-transform: translateX(0px);
		-moz-transform: translateX(0px);
		-ms-transform: translateX(0px);
		-o-transform: translateX(0px);
		transform: translateX(0px);
	}

Y ahora definimos el tiempo que tardará la animación en empezar, dependiendo de la posición del elemento.

.slider__slides li.enter-left:nth-child(1),
.slider__slides li.exit-left:nth-child(1) {
	-webkit-transition-delay: 0.15s;
	-moz-transition-delay: 0.15s;
	-ms-transition-delay: 0.15s;
	-o-transition-delay: 0.15s;
	transition-delay: 0.15s;
}
.slider__slides li.enter-left:nth-child(2),
.slider__slides li.exit-left:nth-child(2) {
	-webkit-transition-delay: 0.20s;
	-moz-transition-delay: 0.20s;
	-ms-transition-delay: 0.20s;
	-o-transition-delay: 0.20s;
	transition-delay: 0.20s;
}
.slider__slides li.enter-left:nth-child(3),
.slider__slides li.exit-left:nth-child(3) {
	-webkit-transition-delay: 0.25s;
	-moz-transition-delay: 0.25s;
	-ms-transition-delay: 0.25s;
	-o-transition-delay: 0.25s;
	transition-delay: 0.25s;
}
.slider__slides li.enter-left:nth-child(4),
.slider__slides li.exit-left:nth-child(4) {
	-webkit-transition-delay: 0.30s;
	-moz-transition-delay: 0.30s;
	-ms-transition-delay: 0.30s;
	-o-transition-delay: 0.30s;
	transition-delay: 0.30s;
}
.slider__slides li.enter-left:nth-child(5),
.slider__slides li.exit-left:nth-child(5) {
	-webkit-transition-delay: 0.35s;
	-moz-transition-delay: 0.35s;
	-ms-transition-delay: 0.35s;
	-o-transition-delay: 0.35s;
	transition-delay: 0.35s;
}
.slider__slides li.enter-left:nth-child(6),
.slider__slides li.exit-left:nth-child(6) {
	-webkit-transition-delay: 0.40s;
	-moz-transition-delay: 0.40s;
	-ms-transition-delay: 0.40s;
	-o-transition-delay: 0.40s;
	transition-delay: 0.40s;
}

.slider__slides li.enter-right:nth-child(6),
.slider__slides li.exit-right:nth-child(6) {
	-webkit-transition-delay: 0.15s;
	-moz-transition-delay: 0.15s;
	-ms-transition-delay: 0.15s;
	-o-transition-delay: 0.15s;
	transition-delay: 0.15s;
}
.slider__slides li.enter-right:nth-child(5),
.slider__slides li.exit-right:nth-child(5) {
	-webkit-transition-delay: 0.20s;
	-moz-transition-delay: 0.20s;
	-ms-transition-delay: 0.20s;
	-o-transition-delay: 0.20s;
	transition-delay: 0.20s;
}
.slider__slides li.enter-right:nth-child(4),
.slider__slides li.exit-right:nth-child(4) {
	-webkit-transition-delay: 0.25s;
	-moz-transition-delay: 0.25s;
	-ms-transition-delay: 0.25s;
	-o-transition-delay: 0.25s;
	transition-delay: 0.25s;
}
.slider__slides li.enter-right:nth-child(3),
.slider__slides li.exit-right:nth-child(3) {
	-webkit-transition-delay: 0.30s;
	-moz-transition-delay: 0.30s;
	-ms-transition-delay: 0.30s;
	-o-transition-delay: 0.30s;
	transition-delay: 0.30s;
}
.slider__slides li.enter-right:nth-child(2),
.slider__slides li.exit-right:nth-child(2) {
	-webkit-transition-delay: 0.35s;
	-moz-transition-delay: 0.35s;
	-ms-transition-delay: 0.35s;
	-o-transition-delay: 0.35s;
	transition-delay: 0.35s;
}
.slider__slides li.enter-right:nth-child(1),
.slider__slides li.exit-right:nth-child(1) {
	-webkit-transition-delay: 0.40s;
	-moz-transition-delay: 0.40s;
	-ms-transition-delay: 0.40s;
	-o-transition-delay: 0.40s;
	transition-delay: 0.40s;
}

Para terminar, daremos forma al menú.

.slider__caret {
	position: absolute;
	width: 15px;
	height: 8px;
	background: url(img/caret.png);
	-webkit-transition: left 0.5s;
	-moz-transition: left 0.5s;
	-ms-transition: left 0.5s;
	-o-transition: left 0.5s;
	transition: left 0.5s;
}

.slider__menu {
	clear: both;
	padding-top: 15px;
	padding-bottom: 10px;
	background: #f5f5f5;
	-webkit-box-shadow: inset 0 2px 2px rgba(0, 0, 0, 0.04);
	box-shadow: inset 0 2px 2px rgba(0, 0, 0, 0.04);
	text-shadow: 0 1px white;
	font-size: 12px;
}

	.slider__menu li {
		float: left;
	}

	.slider__menu a {
		display: inline-block;
		width: 10em;
	}

	.slider__menu a.active,
	.slider__menu a:hover {
		color: #111;
		cursor: pointer;
	}

script.js

Para terminar, tendremos que dar vida a nuestro Slider. Para ello escribiremos un pequeño código, utilizando el framework jQuery como viene siendo costumbre.

// Determinamos el ancho de cada sección y lo centramos.
// Hay que calcularlo porque estamos posicionando el elemento como absolute.
$('.slider__slides ul').each(function() {
	var innerWidth = $(this).innerWidth();

	$(this).css({
		width: innerWidth,
		position: 'absolute',
		left: ($('.slider').width() - innerWidth) / 2
	});
});

// Guardamos el número de la página actual.
var actualPage = -1;

$('.slider__menu a').click(function(e) {
	e.preventDefault();

	// Próxima página.
	var nextPage = $(this).index('.slider__menu a');

	// Cambiamos los colores del menú.
	$('.slider__menu a').removeClass('active');
	$(this).addClass('active');

	// El slider se acaba de inicializar.
	if (actualPage == -1) {
		$('.slider__slides ul:first li').addClass('enter-left');
	}
	// Desplazamos el contenido hacia la izquierda.
	else if (nextPage > actualPage) {
		$('.slider__slides ul:eq(' + actualPage + ') li')
			.removeClass('enter-left enter-right')
			.addClass('exit-left');
		$('.slider__slides ul:eq(' + nextPage + ') li')
			.removeClass('exit-right')
			.addClass('enter-left');
	}
	// Hacia la derecha.
	else if (nextPage < actualPage) {
		$('.slider__slides ul:eq(' + actualPage + ') li')
			.removeClass('enter-left enter-right')
			.addClass('exit-right');
		$('.slider__slides ul:eq(' + nextPage + ') li')
			.removeClass('exit-left')
			.addClass('enter-right');
	}

	// Movemos el indicador.
	$('.slider__caret').css('left', $(this).position().left + $(this).width() / 2 - $('.slider__caret').width() / 2);

	// Cambiamos la página actual.
	actualPage = nextPage;
});

// Al cargar la página provocamos la carga de la primera sección.
$('.slider__menu a:first').click();

Fin

Y con esto podemos dar por sentado el tutorial. Como podéis ver, no es tan difícil hacer algo así siempre y cuando se observe y se plantee correctamente.

Una vez más, podéis ver el resultado o bien el código en GitHub. No dudéis en dejar vuestras opiniones por escrito, o bien dar ideas sobre nuevos tutoriales que os gustaría ver. ¡Nos vemos!

comments powered by Disqus