Create a parallax effect with background image
by Jordan Sayner
HTML
<div class="spacer">Scroll Down</div>
<section data-parallax>
<img src="https://picsum.photos/id/1015/1200/800" alt="Parallax 1">
<div class="content">Parallax One</div>
</section>
<div class="spacer">Spacer</div>
<section data-parallax>
<img src="https://picsum.photos/id/1016/1200/800" alt="Parallax 2">
<div class="content">Parallax Two</div>
</section>
<div class="spacer">Another Spacer</div>
<section data-parallax>
<img src="https://picsum.photos/id/1018/1200/800" alt="Parallax 3">
<div class="content">Parallax Three</div>
</section>
<div class="spacer">End of Page</div>
CSS
html, body {
margin: 0;
padding: 0;
}
.spacer {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
background: #eee;
}
[data-parallax] {
position: relative;
height: 100vh;
overflow: hidden;
}
[data-parallax] img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 120%;
object-fit: cover;
transform: translateY(0);
will-change: transform;
z-index: -1;
}
.content {
position: relative;
z-index: 1;
padding-top: 40vh;
text-align: center;
color: white;
font-size: 3rem;
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.6);
}
JavaScript
const parallaxSections = document.querySelectorAll('[data-parallax]');
let latestScrollY = 0;
let ticking = false;
function updateParallax() {
parallaxSections.forEach(section => {
const image = section.querySelector('img');
const rect = section.getBoundingClientRect();
const sectionTop = window.scrollY + rect.top;
const sectionHeight = rect.height;
const windowHeight = window.innerHeight;
if (
latestScrollY + windowHeight > sectionTop &&
latestScrollY < sectionTop + sectionHeight
) {
const offset = (latestScrollY - sectionTop) * 0.5; // Adjust speed here
image.style.transform = `translateY(${offset}px)`;
}
});
ticking = false;
}
function onScroll() {
latestScrollY = window.scrollY;
if (!ticking) {
requestAnimationFrame(updateParallax);
ticking = true;
}
}
window.addEventListener('scroll', onScroll);