<section class="lorem">
please <br/> scroll down ⬇
</section>
<section class="scroll-section">
<div class="container">
<div class="container_inner">
<div class="scroll-section__inner">
<figure class="scroll-section__figure">
<img class="scroll-section__image" src="https://images.unsplash.com/photo-1495360010541-f48722b34f7d?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8Y2F0fGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&h=500&q=80" alt="">
</figure>
<figure class="scroll-section__figure">
<img class="scroll-section__image" src="https://images.unsplash.com/photo-1491485880348-85d48a9e5312?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&h=500&q=80" alt="">
</figure>
<figure class="scroll-section__figure">
<img class="scroll-section__image" src="https://images.unsplash.com/photo-1501474466180-4704b8607ba5?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDEyfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&h=500&q=80" alt="">
</figure>
<figure class="scroll-section__figure">
<img class="scroll-section__image" src="https://images.unsplash.com/photo-1548366086-7f1b76106622?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&h=500&q=80" alt="">
</figure>
<figure class="scroll-section__figure">
<img class="scroll-section__image" src="https://images.unsplash.com/photo-1548802673-380ab8ebc7b7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDE2fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&h=500&q=80" alt="">
</figure>
<div class="scroll-section__content">
<div class="scroll-section__text">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorum repudiandae aspernatur esse! Voluptate tenetur
</div>
</div>
<div class="scroll-section__spacer"></div>
</div>
</div>
</div>
</section>
<section class="lorem">
thank you for scrolling <br/> now scroll up ⬆
</section>
*, *::before, *::after {
box-sizing: border-box;
}
body, figure {
margin: 0;
}
img {
vertical-align: middle;
max-width: 100%;
}
.container {
width: 75%;
margin: 0 auto;
padding: 0 15px;
}
.lorem {
height: 80vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
font-family: sans-serif;
font-size: 3rem;
background-color: #e4e4e4;
}
.scroll-section {
padding: 70px 0;
overflow: hidden;
background-color: #00211e;
}
.scroll-section-spacer {
background-color: #00211e;
}
.scroll-section__inner {
display: flex;
}
.scroll-section__figure {
flex-shrink: 0;
margin-right: 30px;
width: 70%;
}
.scroll-section__image {
display: block;
width: 100%;
}
.scroll-section__content {
padding: 15px;
width: calc(30% - 30px);
min-width: 150px;
flex-shrink: 0;
align-self: center;
background-color: #fff;
font-size: 1.25em;
font-family: sans-serif;
opacity: 0;
transition: opacity 500ms linear;
}
.scroll-section__content--visible {
opacity: 1;
}
.scroll-section__spacer {
width: calc(50vw - 50%);
flex-shrink: 0;
}
const section = document.querySelector('.scroll-section');
const sectionContent = section.querySelector('.scroll-section__content');
const containerInner = section.querySelector('.container_inner');
const sectionFigures = [section.querySelectorAll('.scroll-section__figure')];
const windowController = new ScrollMagic.Controller();
const sectionController = new ScrollMagic.Controller({
container: section,
vertical: false
});
const inertSectionController = inertController(sectionController, 0.07);
new ScrollMagic.Scene({
offset: 0,
triggerHook: 0,
triggerElement: section,
duration: '300%',
})
// .addIndicators() // add indicators (requires plugin)
.setPin(section, { spacerClass: 'scroll-section-spacer' })
.on('progress', (event) => {
const scrollLeft = event.progress * (section.scrollWidth - section.offsetWidth);
inertSectionController(scrollLeft);
// sectionController.scrollTo(scrollLeft);
})
.addTo(windowController);
const figures = sectionFigures.map(figure => {
const img = figure.querySelector('.scroll-section__image');
const scene = new ScrollMagic.Scene({
offset: 0,
triggerHook: 0,
triggerElement: figure,
duration: figure.clientWidth,
})
//.addIndicators() // add indicators (requires plugin)
.on('progress', (event) => {
const progress = event.progress;
const scale = lerp(0.55, 1, clamp(progress * 2, 0, 1));
const ty = lerp(22.5, 0, clamp(progress * 2, 0, 1));
const rot = lerp(270, 360, clamp(progress * 2, 0, 1));
const opacity = lerp(1, 0, clamp(progress * 2 - 1, 0, 1));
img.style.transform = `translateY(${ty}%) scale(${scale}) rotate(${rot}deg)`;
img.style.opacity = opacity;
})
.progress(0)
.addTo(sectionController);
return { figure, img, scene }
});
function onResize() {
const triggerHook = containerInner.offsetLeft / section.clientWidth;
figures.forEach(({ scene, figure }) => {
const figureWidth = figure.clientWidth;
scene.triggerHook(triggerHook);
scene.duration(figureWidth * 2);
scene.offset(figureWidth * -1);
});
}
onResize();
window.addEventListener('resize', onResize);
new ScrollMagic.Scene({
offset: 150,
triggerHook: 1,
triggerElement: sectionContent,
})
.setClassToggle(sectionContent, 'scroll-section__content--visible')
.addTo(sectionController);
// =============== utils ===============
function lerp(v0, v1, t) {
return v0 * (1 - t) + v1 * t;
}
function clamp(val, min, max) {
return Math.min(Math.max(val, min), max);
}
function inertController(controller, inert = 0.05) {
let rafId = null;
let prevpos = controller.scrollPos();
let newpos;
const loop = (now) =>{
const smoothpos = Math.round(prevpos + (newpos - prevpos) * inert);
controller.scrollTo(smoothpos);
prevpos = smoothpos;
if (smoothpos !== newpos) {
rafId = requestAnimationFrame(loop);
}
else {
rafId = null;
}
}
return (pos) => {
newpos = pos;
cancelAnimationFrame(rafId);
rafId = requestAnimationFrame(loop);
}
}
This Pen doesn't use any external CSS resources.