JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.0/gsap.min.js"></script>
<section class="viewport">
<div id="scroll-container" class="scroll-container">
<div class="content">
<div class="one"></div>
<div class="two"><div class="header">Зафиксированный</div></div>
<div class="three"></div>
</div>
</div>
</section>
CSS
body {
overflow-x: hidden;
overflow-y: scroll;
padding:0;
}
.viewport {
overflow: hidden;
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.scroll-container {
position: absolute;
overflow: hidden;
z-index: 10;
display: flex;
justify-content: center;
backface-visibility: hidden;
transform-style: preserve-3d;
}
.content {
width: 500px;
}
.one {
background: #244FFD;
height: 500px;
}
.two {
background: #FD3F32;
height: 1000px;
}
.header {
background: rgba(204, 204, 204, 0.4);
height: 150px;
text-align: center;
width: 100%;
}
.three {
background: #59FD85;
height: 1000px;
}
JavaScript
var html = document.documentElement;
var body = document.body;
var stickyElems = document.querySelectorAll(".header");
var scroller = {
target: document.querySelector("#scroll-container"),
ease: 0.05, // <= scroll speed
endY: 0,
y: 0,
resizeRequest: 1,
scrollRequest: 0,
};
var requestId = null;
gsap.set(scroller.target, {
rotation: 0.01,
force3D: true
});
window.addEventListener("load", onLoad);
function onLoad() {
updateScroller();
window.focus();
window.addEventListener("resize", onResize);
document.addEventListener("scroll", onScroll);
}
function updateScroller() {
var resized = scroller.resizeRequest > 0;
if (resized) {
var height = scroller.target.clientHeight;
body.style.height = height + "px";
scroller.resizeRequest = 0;
}
var scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;
scroller.endY = scrollY;
scroller.y += (scrollY - scroller.y) * scroller.ease;
if (Math.abs(scrollY - scroller.y) < 0.05 || resized) {
scroller.y = scrollY;
scroller.scrollRequest = 0;
}
gsap.set(scroller.target, {
y: -scroller.y
});
// -------------------------
// ВООООООТ ОНО
// -------------------------
stickyElems.forEach(elem => {
const topka = elem.getBoundingClientRect().top;
const y = gsap.getProperty(elem, "y");
const wheight = document.documentElement.clientHeight;
if (y >= elem.parentNode.clientHeight - elem.clientHeight &&
elem.parentNode.getBoundingClientRect().top + scroller.y + elem.parentNode.clientHeight - elem.clientHeight <= scroller.y) {
gsap.set(elem, {y: elem.parentNode.clientHeight - elem.clientHeight});
console.log('Фиксация внизу')
} else if (topka <= 0 || y > 0) {
gsap.set(elem, {y: scroller.y - 500});
console.log('ЕДЕТ')
} else {
gsap.set(elem, {y: 0});
console.log('Блок находится в начале.')
}
});
...