I'm building parallax banner images with text overlays and I DON'T want to use css. background images to make this happen as I'm building a Wordpress Theme that can be altered by the client.
Instead, I'd like to keep the DIV with the image overlay (and text), positioned relative in the document flow and set it a height of around 450px for this, and have the associated image behind it in another DIV positioned absolute that moves in a parallax manor on scroll.
So... As the page scrolls up/down, the image behind moves up/down with it, but at a slower pace, still RELATIVE TO ITS PARENT DIV.
I can do it with 1 image per page. BUT, when I add more I need the pageYOffset on the 2nd and 3rd images to ONLY begin moving the image, when the parent DIV enters the viewport at the bottom of the screen.
As such I've tried many JS solutions including my last go, using intersection observers, to try to stop the later parallaxes from starting early but to no avail...
Any help please...
Here's the mark up
<!-- First Parallax Content -->
<div id="parallaxOne" class="parallax-content-container">
<!-- Banner Image -->
<div id="parallaxTargetOne" class="parallax-image-wrapper">
<img src="IMG"alt="ALT">
</div>
<div class="inner-wrapper contained-content">
<div class="quote-container">
<!-- Featured Title -->
<h2>FEATURED TITLE</h2>
<!-- Sub Title -->
<h3>SUB TITLE</h3>
</div>
</div>
</div>
<!-- Second Parallax Content -->
<div id="parallaxTwo" class="parallax-content-container">
<!-- Banner Image -->
<div id="parallaxTargetTwo" class="parallax-image-wrapper">
<img src="IMG"alt="ALT">
</div>
<div class="inner-wrapper contained-content">
<div class="quote-container">
<!-- Featured Title -->
<h2>FEATURED TITLE</h2>
<!-- Sub Title -->
<h3>SUB TITLE</h3>
</div>
</div>
</div>
Here's the simple css
.parallax-content-container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 450px;
// overflow: hidden;
border: 8px dotted green; // To See The Problem
}
.parallax-image-wrapper {
position: absolute;
height: 100vh;
width: 100%;
top: 0;
left: 0;
z-index: -1;
border: 10px solid red; // To See The Problem
}
.parallax-image-wrapper:after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.025);
}
.parallax-image-wrapper > img {
height: 100%;
object-fit: cover;
object-position: center center;
}
.quote-container h2,
.quote-container h3 {
color: #fff;
text-shadow: 0 0 30px rgba(0, 0, 0, 0.8);
}
Heres my JS | The First Way I Tried
const parallaxOne = document.getElementById('parallaxOne');
const parallaxTwo = document.getElementById('parallaxTwo');
window.addEventListener('scroll', function (event) {
if (parallaxOne.getBoundingClientRect().top < window.innerHeight) {
const firstParallaxEffect = element1 => {
console.log('In the viewport');
let scrolled = window.pageYOffset;
let rate = scrolled * -0.175;
element1.style.top = window.pageYOffset;
element1.style.transform = 'translate3d(0px, ' + rate + 'px, 0px)';
};
firstParallaxEffect(document.getElementById('parallaxTargetOne'));
}
if (parallaxTwo.getBoundingClientRect().top < window.innerHeight) {
const secondParallaxEffect = element => {
console.log('In the viewport');
let scrolled = window.pageYOffset;
let rate = scrolled * -0.175;
element.style.top = window.pageYOffset;
element.style.transform = 'translate3d(0px, ' + rate + 'px, 0px)';
};
secondParallaxEffect(document.getElementById('parallaxTargetTwo'));
}
});
The Second Way I Tried
const parallaxOne = document.getElementById('parallaxOne');
const elementOne = document.getElementById('parallaxTargetOne');
const optionsOne = {
root: null,
threshold: 0,
rootMargin: '0px',
};
const parallaxTwo = document.getElementById('parallaxTwo');
const elementTwo = document.getElementById('parallaxTargetTwo');
const optionsTwo = {
root: null,
threshold: 0,
rootMargin: '0px',
};
const obsOne = new IntersectionObserver(function (entries, obsOne) {
entries.forEach(entry => {
window.addEventListener('scroll', function (event) {
let scroll = window.pageYOffset;
let rate = scroll * -0.17;
elementOne.style.transform =
'translate3d(0px, ' + rate + 'px, 0px)';
});
});
}, optionsOne);
obsOne.observe(parallaxOne);
const obsTwo = new IntersectionObserver(function (entries, obsTwo) {
entries.forEach(entry => {
window.addEventListener('scroll', function (event) {
let scroll = window.pageYOffset;
let rate = scroll * -0.17;
elementTwo.style.transform =
'translate3d(0px, ' + rate + 'px, 0px)';
});
});
}, optionsTwo);
obsTwo.observe(parallaxTwo);
