Parallax Scroller (CSS)
by Eric Hynds
HTML
<div class="buttons">
<button id="prev">Prev</button>
<button id="next">Next</button>
</div>
<div id="hero-container">
<div class="hero-image" style="background-image: url(http://placeimg.com/640/480/any?1)">
<div class="hero-text">
<div>HERO 1</div>
<div>More info on Hero 1.</div>
</div>
</div>
<div class="hero-image" style="background-image: url(http://placeimg.com/640/480/any?2);">
<div class="hero-text">
<div>HERO 2</div>
<div>More info on Hero 2.</div>
</div>
</div>
<div class="hero-image" style="background-image: url(http://placeimg.com/640/480/any?3);">
<div class="hero-text">
<div>HERO 3</div>
<div>More info on Hero 3.</div>
</div>
</div>
</div>
CSS
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.buttons {
position: absolute;
z-index: 10;
top: 20px;
left: 20px;
}
.hero-image:not(:first-child) {
transform: translateY(100%);
}
.hero-image:not(:first-child) .hero-text {
transform: translateY(1000%);
}
.hero-image.reverse {
transform: translateY(-100%);
}
.hero-image.reverse .hero-text {
transform: translateY(-1000%);
}
.slide-in {
transition: all 2s ease;
transform: translateY(0) !important;
}
.slide-in .hero-text {
transition: all 2s ease;
transform: translateY(0) !important;
}
.slide-out {
transition: all 2s ease;
transform: translateY(-40%) !important;
}
.slide-out .hero-text {
transition: all 2s ease;
transform: translateY(-1000%) !important;
}
.slide-out.reverse {
transition: all 2s ease;
transform: translateY(40%) !important;
}
.slide-out.reverse .hero-text {
transition: all 2s ease;
transform: translateY(1000%) !important;
}
#hero-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.hero-image {
transform: translate3d(0, 0, 0);
background-size: cover;
width: 100%;
height: 100%;
position: absolute;
}
.hero-text {
position: absolute;
left: 10%;
top: 70%;
color: #FFF;
font-family: sans-serif;
font-size: 30px;
text-shadow: 0px 0px 8px black, 0px 0px 2px black;
}
JavaScript
(function () {
var classes = 'slide-in slide-out reverse'
var transitionEnd = 'webkitTransitionEnd transitionend';
function Parallax(elem) {
this.$container = $(elem);
this.$slides = this.$container.children();
}
Parallax.prototype._transitionEnd = function (event) {
this.$container[this.direction === 'next' ? 'append' : 'prepend'](event.target);
this.$slides.removeClass(classes).off(transitionEnd)
this.transitioning = false;
};
Parallax.prototype.next = function () {
if (this.transitioning) return;
var $slides = this.$container.children();
this.direction = 'next';
this.transitioning = true;
$slides.eq(1).addClass('slide-in');
$slides.eq(0).on(transitionEnd, this._transitionEnd.bind(this)).addClass('slide-out');
};
Parallax.prototype.prev = function () {
if (this.transitioning) return;
var $slides = this.$container.children();
this.direction = 'prev';
this.transitioning = true;
$slides.last().addClass('reverse');
setTimeout(function () {
$slides.eq(0).addClass('slide-out reverse');
$slides.eq(-1).on(transitionEnd, this._transitionEnd.bind(this)).addClass('slide-in');
}.bind(this), 10)
};
$.fn.parallax = function () {
return this.each(function () {
$.data(this, 'parallax', new Parallax(this));
});
};
})();
$(document).ready(function () {
var $container = $('#hero-container').parallax();
var obj = $container.data('parallax');
$('#prev').on('click', function () {
obj.prev();
});
$('#next').on('click', function () {
obj.next();
});
});