<div class="layout min-h-dvh bg-gray-100">
<header class="sticky top-0 z-10 h-[57px] max-h-[57px] shrink-0 border-b bg-gray-100" style="grid-area: header">header</header>
<div id="content" class="h-fit" style="grid-area: content">
<div>
<div class="content gap-4 max-w-6xl w-full mx-auto p-4">
<div class="relative flex flex-col gap-4" style="grid-area: intro">
<div class="rounded-lg bg-white p-6">intro</div>
</div>
<div class="flex flex-col gap-4 " style="grid-area: main">
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
<div class="min-h-96 rounded-lg bg-white p-6">post</div>
</div>
<aside class="relative block w-64 shrink-0" style="grid-area: aside">
<div id="aside-wrapper" class="flex h-full flex-col justify-end">
<div id="aside" class="sticky bottom-4 flex flex-col gap-4" style="backface-visibility: hidden;">
<div id="aside-top" class="shrink-0">top marker</div>
<div class="min-h-72 rounded-lg bg-white p-6">widget</div>
<div class="min-h-72 rounded-lg bg-white p-6">widget</div>
<div class="min-h-72 rounded-lg bg-white p-6">widget</div>
<div class="min-h-72 rounded-lg bg-white p-6">widget</div>
<div class="min-h-72 rounded-lg bg-white p-6">widget</div>
<div id="aside-bottom">bottom marker</div>
</div>
</div>
</aside>
</div>
</div>
</div>
</div>
.layout {
display: grid;
grid-template-columns: 288px calc(100% - 288px);
grid-template-rows: min-content min-content min-content 1fr min-content;
grid-template-areas:
"banner banner"
"header header"
"subheader subheader"
"navbar content"
"navbar footer"
"navbar fixedBottom";
}
.content {
display: grid;
grid-template-columns: 1fr 0fr;
grid-template-rows: 0fr 1fr;
grid-template-areas:
"intro intro"
"main aside";
}
let lastScrollTop = 0;
let lastScrollDirection = "down";
let scrollDirection = "down";
document.addEventListener("scroll", function () {
const content = document.getElementById("content");
const asideWrapper = document.getElementById("aside-wrapper");
const aside = document.getElementById("aside");
const asideTop = document.getElementById("aside-top");
const asideBottom = document.getElementById("aside-bottom");
const currentScrollTop = window.scrollY;
if (currentScrollTop > lastScrollTop) {
scrollDirection = "down";
} else {
scrollDirection = "up";
}
if (lastScrollDirection !== scrollDirection) {
aside.classList.add("static");
aside.classList.remove("sticky", "top-[73px]", "bottom-4");
// Вот здесь какое значение должно быть?
aside.style.transform = `translate3d(0, ${
aside.getBoundingClientRect().top -
asideWrapper.getBoundingClientRect().top
}px, 0)`;
if (scrollDirection === "up") {
asideWrapper.classList.remove("justify-end");
asideWrapper.classList.add("justify-start");
}
}
if (isElementOnScreen(asideBottom) && scrollDirection === "down") {
aside.classList.remove("static", "top-[73px]");
aside.classList.add("sticky", "bottom-4");
asideWrapper.classList.remove("justify-start");
asideWrapper.classList.add("justify-end");
// aside.style.transform = `translate3d(0, 0, 0)`;
}
if (isElementOnScreen(asideTop) && scrollDirection === "up") {
aside.classList.remove("static", "bottom-4");
aside.classList.add("sticky", "top-[73px]");
aside.style.transform = `translate3d(0, 0, 0)`;
}
lastScrollTop = currentScrollTop;
lastScrollDirection = scrollDirection;
});
function isElementOnScreen(element) {
const rect = element.getBoundingClientRect();
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
const windowHeight =
window.innerHeight || document.documentElement.clientHeight;
if (
rect.left < 0 ||
rect.right > windowWidth ||
rect.top < 0 ||
rect.bottom > windowHeight
) {
return false;
}
return true;
}
This Pen doesn't use any external CSS resources.