Efeito Parallax em CSS e jQuery

Provavelmente você já deve ter visto o efeito parallax em alguma mídia perto de você, seja em um jogo, um vídeo, um site, ou qualquer outro local. Ele consiste em dar profundidade em elementos que estão parados adicionando movimento em diferentes velocidades de acordo com a distância desejada para determinado elemento (Veja Paralaxe astronômica).

Um exemplo interessante é que você pode visualizar este efeito até mesmo na vida real simplesmente caminhando ou andando em um veículo qualquer.

Quando qualquer coisa se move na sua frente, principalmente quando seu campo de profundidade é maior (como andar na calçada na beira do mar, por exemplo) você pode observar que à medida que avança os objetos ao seu lado se movem em velocidades diferentes; do objeto mais ao fundo, que se move mais lentamente, para o objeto mais próximo, cada vez mais depressa.

Exemplo em vídeo

Abaixo você pode visualizar um exemplo do efeito parallax em vídeo:

Criar um layout com o efeito parallax é basicamente isso, fazer com que elementos se movam em velocidades diferentes de acordo a distância desejada.

Neste tutorial, você vai aprender a fazer exatamente isso com os elementos de sua página.

Exemplo e download

Para este tutorial, vamos utilizar HTML, CSS e jQuery (JavaScript) para criar um efeito parallax bem simples, mas que vai lhe dar ideias para seus próximos layouts.

Demo

Você pode visualizar um exemplo do que vamos criar no link abaixo:

Download

Você também pode fazer o download do que viu acima no link abaixo:

A ideia

Existem vários métodos para criar o efeito parallax, também existem vários modelos desse efeito, porém, em específico para nosso tutorial, vamos criar o efeito na rolagem da página, seja para cima ou para baixo.

Vamos utilizar duas opções do CSS para atingir o objetivo, background-position e a opção de posição bottom do elemento, ambas as opções serão manipuladas pelo jQuery.

A opção background-position será aplicada a um elemento maior que vai estar no fundo, ou seja, um background que vai rolar ao contrário da página. À medida que a página rola para baixo, a posição do background irá rolar a imagem para cima.

A opção bottom será aplicada a elementos menores, mas dará o mesmo efeito descrito anteriormente, enquanto a página rola para baixo, a posição bottom do elemento será incrementada, fazendo com que ele role para cima.

A diferença aqui é que os elementos menores terão a velocidade bem mais elevada do que o fundo.

O HTML

Para nosso HTML, teremos o seguinte:

<div class="parallax div1" data-divisor="2">
    <div class="text">Olha o primeiro gatinho!!!</div>
</div>

Muito simples, não?

O DIV com classe parallax é o principal elemento aqui, nele teremos que ter mais uma classe e uma opção chamada de data-divisor.

Veja detalhes de cada classe e o atributo data-divisor:

  • parallax – A classe principal, onde teremos a configuração geral dos elementos que terão o efeito no fundo.
  • div1 – Essa pode ser qualquer classe que preferir, porém, ela deve existir para que você selecione um único background para cada elemento;
  • data-divisor – Esse atributo será utilizado como divisor para o jQuery, quando maior o número, mais lento o background irá rolar.

O DIV com classe text, é o texto ou elemento que você deseja que role mais rápido que o fundo, ela não é necessária se você não quiser.

Além disso, se você quiser, pode adicionar outros elementos após a primeira DIV, e assim, intercalar texto ou qualquer outra coisa que preferir no meio das sessões do seu efeito parallax.

O HTML completo

Como descrevi anteriormente, aquele trecho era apenas explicativo, já que com apenas uma sessão não haveria rolagem da página.

Para meu exemplo, criei seis sessões, das quais você pode ver o código completo abaixo:

<!doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Efeito Parallax - Tutsup</title>
		
		<link rel="stylesheet" href="css/style.css">
		<script src="js/jquery.js"></script>
		<script src="js/scripts.js"></script>
	</head>

	<body>
		<div class="parallax div1" data-divisor="2">
			<div class="text">Olha o primeiro gatinho!!!</div>
		</div>
		
		<div class="qualquer_coisa">
			Um texto qualquer com qualquer tag HTML.			
		</div>
		
		<div class="parallax div2" data-divisor="4">
			<div class="text">Olha o segundo gatinho!!!</div>
		</div>
		
		<div class="qualquer_coisa">
			Um texto qualquer com qualquer tag HTML.			
		</div>
		
		<div class="parallax div3" data-divisor="3">
			
			<div class="text">Olha o terceiro gatinho!!!</div>
		</div>
		
		<div class="qualquer_coisa">
			Um texto qualquer com qualquer tag HTML.			
		</div>
		
		<div class="parallax div4">
			
			<div class="text">Olha o quarto gatinho!!!</div>
		</div>
		
		<div class="qualquer_coisa">
			Um texto qualquer com qualquer tag HTML.			
		</div>
		
		<div class="parallax div5" data-divisor="2">
			<div class="text">Olha o quinto gatinho!!!</div>
		</div>
		
		<div class="qualquer_coisa">
			Um texto qualquer com qualquer tag HTML.			
		</div>
		
		<div class="parallax div6">
			<div class="text">Olha o sexto gatinho!!!</div>
		</div>

	</body>
</html>

Estou intercalando outro DIV com classe qualquer_coisa. Esse DIV pode receber literalmente qualquer coisa que preferir – pode até ser removido, se não for de seu interesse.

O CSS

Agora a coisa começa a ficar interessante.

Primeiramente, faço um reset no CSS (faça como preferir):

* {
	margin: 0;
	padding: 0;
}
body,
html {
	height:100%;
	font-family:sans-serif;
	line-height:1.5;
}

A segunda parte, configura o texto (.text) em si:

/* Configura os textos */
.text {
	color: #fff;
	font-size: 40px;
	text-shadow: 2px 2px 0 #000;
	position: absolute;
	background-color: rgba(0,0,0,0.8);
	padding: 20px;
	line-height: 1.5;
	width: 200px;
	bottom: 100px;
	left: 10%;
}

Para a classe parallax, temos o seguinte:

.parallax{
	width: 100%;
	height: 100%;
	background-attachment: fixed;
	background-size: cover;
	background-position: 50% 0;
	position: relative;
}

O segredo aqui está na largura e altura (100% da tela), no modo que o background vai se comportar, que é fixed (fixo enquanto a tela rola) e background-size: cover; que faz com que o background sempre preencha a tela inteira.

Para colocar um background diferente para cada uma das sessões, utilizo a segunda classe do elemento, veja:

.div1 {
	background-image: url(../imagens/11.jpg);
}
.div2 {
	background-image: url(../imagens/12.jpg);
}
.div3 {
	background-image: url(../imagens/13.jpg);
}
.div4 {
	background-image: url(../imagens/14.jpg);
}
.div5 {
	background-image: url(../imagens/15.jpg);
}
.div6 {
	background-image: url(../imagens/16.jpg);
}

Por fim, configuro o DIV que vem no meio de cada sessão (.qualquer_coisa).

.qualquer_coisa {
	padding: 20px;
}
.qualquer_coisa h2, 
.qualquer_coisa p{
	padding: 20px;
	margin: 1.3 0;
}

O CSS completo

Se você é daqueles que gosta de copiar e colar, segue o CSS completo:

* {
	margin: 0;
	padding: 0;
}
body,
html {
	height:100%;
	font-family:sans-serif;
	line-height:1.5;
}

/* Configura os textos */
.text {
	color: #fff;
	font-size: 40px;
	text-shadow: 2px 2px 0 #000;
	position: absolute;
	background-color: rgba(0,0,0,0.8);
	padding: 20px;
	line-height: 1.5;
	width: 200px;
	bottom: 100px;
	left: 10%;
}

/* Configura os elementos "parallax" */
.parallax{
	width: 100%;
	height: 100%;
	background-attachment: fixed;
	background-size: cover;
	background-position: 50% 0;
	position: relative;
}

/* Configura um background para cada elemento */
.div1 {
	background-image: url(../imagens/11.jpg);
}
.div2 {
	background-image: url(../imagens/12.jpg);
}
.div3 {
	background-image: url(../imagens/13.jpg);
}
.div4 {
	background-image: url(../imagens/14.jpg);
}
.div5 {
	background-image: url(../imagens/15.jpg);
}
.div6 {
	background-image: url(../imagens/16.jpg);
}

/* Configura o texto lorem ipsum */
.qualquer_coisa {
	padding: 20px;
}
.qualquer_coisa h2, 
.qualquer_coisa p{
	padding: 20px;
	margin: 1.3 0;
}

O jQuery

Apenas com CSS e HTML, você já consegue atingir um objetivo mais ou menos interessante (eu diria, quase um parallax), porém, o jQuery é que vai movimentar estes elementos à medida que a página é rolada.

A primeira coisa é "iniciar" o jQuery:

$(function(){
    // O código vem aqui
}); // jQuery

Dentro dessa função, vamos capturar o evento scroll da página (rolagem):

$(window).scroll(function(){
    // Captura os pixels de distância do topo
    var window_scrolltop = $(this).scrollTop();
    
    // O RESTO VEM AQUI

});

Agora precisamos capturar cada elemento que tem a classe parallax. Veja:

// Passa por cada elemento com a classe .parallax
$('.parallax').each(function(){
	// Joga o objeto $('.parallax')em uma variável
	var obj = $(this);
	
	// O RESTO VEM AQUI
});

Agora vamos fazer todo o restante dentro dessa função.

A primeira coisa que temos que fazer, é garantir que vamos trabalhar apenas com o elemento visível na tela, então:

if ( window_scrolltop >= obj.position().top - obj.height() 
	&& window_scrolltop <= obj.position().top + obj.height()) {
	// Agora temos a garantia
}

Ou seja, se (if) a distância de rolagem (window_scrolltop) for maior ou igual (>=) a distância do elemento referente ao topo (obj.position().top), menos (-) a altura do objeto (obj.height()), e se a distância de rolagem (window_scrolltop) for menor ou igual (<=) a distância do elemento referente ao topo (obj.position().top), mais (+) a altura do elemento (obj.height()).

Isso garante que só alteremos alguma propriedade do elemento quando for necessário.

Agora precisamos obter o valor do divisor, caso ele tenha sido configurado no HTML:

// O atributo data-divisor vai definir a velocidade do efeito
var divisor = typeof obj.attr('data-divisor') == 'undefined' ? 4 : obj.attr('data-divisor');

Coloquei um valor padrão (4) caso não queira configurar este atributo no HTML.

Agora precisamos da posição do background, porém, é necessário fazer um pequeno truque se ele for o primeiro objeto da lista elementos. Isso acontece, porque não é possível rolar a página acima do primeiro elemento, portanto, tive que fazer o seguinte:

// Corrige a diferença do primeiro elemento
if ( obj.is(':first-child') ) {
	var bg_pos = ( window_scrolltop - obj.position().top ) / divisor;
} else {
	var bg_pos = ( window_scrolltop - obj.position().top + ( obj.height() - 100 ) ) / divisor;
}

Ou seja, se o elemento for o primeiro, a posição do background é a distância de rolagem da janela, menos a posição do elemento referente ao topo da janela, divido pelo divisor que estivermos utilizando; caso contrário, a posição do background será a distância de rolagem da janela, menos a posição do elemento referente ao topo da janela, mais o tamanho do elemento menos cem, dividido pelo divisor.

Agora é só aplicar o CSS ao DIV com classe parallax:

// Modifica a posição do bg
obj.css({
	'background-position' : '50% -' + bg_pos + 'px'
});

Para que o texto role mais rápido, aplicamos o seguinte:

// Animação do primeiro texto
obj.children('.text').css({
	'bottom' : ( window_scrolltop - obj.position().top + 100 ) + 'px'
});

A posição inferior do elemento será incrementada pela distância de rolagem da janela, menos a posição do elemento parallax referente ao topo, mais cem.

O jQuery completo

Mais uma vez, se você é daquelas pessoas que gosta de copiar e colar, segue o código completo:

$(function(){
	$(window).scroll(function(){
		var window_scrolltop = $(this).scrollTop();
		
		// Passa por cada elemento com a classe .parallax
		$('.parallax').each(function(){
			var obj = $(this);
			
		// Garante que apenas trabalhemos no elemento que está visível na tela
		if ( window_scrolltop >= obj.position().top - obj.height() 
			&& window_scrolltop <= obj.position().top + obj.height()) {
			
			// O atributo data-divisor vai definir a velocidade do efeito
			var divisor = typeof obj.attr('data-divisor') == 'undefined' ? 4 : obj.attr('data-divisor');
			
			// Corrige a diferença do primeiro elemento
			if ( obj.is(':first-child') ) {
				var bg_pos = ( window_scrolltop - obj.position().top ) / divisor;
			} else {
				var bg_pos = ( window_scrolltop - obj.position().top + ( obj.height() - 100 ) ) / divisor;
			}
			
			// Modifica a posição do bg
			obj.css({
				'background-position' : '50% -' + bg_pos + 'px'
			});
			
			// Animação do primeiro texto
			obj.children('.text').css({
				'bottom' : ( window_scrolltop - obj.position().top + 100 ) + 'px'
			});
			
		} // Garante que apenas trabalhemos no elemento que está visível na tela
		}); // $('.parallax').each(function(){ ...
	}); // $(window).scroll(function(){ ...
}); // jQuery

É isso!

Efeito Parallax em CSS e jQuery

Esse é o efeito parallax feito de maneira bem simples. Você pode incrementar, ou fazer qualquer alteração no código para adaptar às suas necessidades.

Se encontrar algum erro ou quiser deixar alguma sugestão, basta deixar um comentário. Críticas são sempre bem vindas.

Caso queira ver novamente nosso exemplo, ou baixar o código, segue abaixo:

Demo

Download

Espero que seja de utilidade.