Skip to content

Commit dc95a20

Browse files
committed
Add animated section background on scroll
1 parent 3dacfde commit dc95a20

2 files changed

Lines changed: 104 additions & 4 deletions

File tree

misc/landing-page/src/components/Header.astro

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,15 @@ const openNewTab = { target: "_blank", rel: "noopener noreferrer" };
130130

131131
if (!elementBehind) return;
132132

133+
const section = elementBehind.closest<HTMLElement>(".section-bg");
134+
135+
const sectionBackground = section?.dataset.background || "light";
136+
const sectionAnimationProgress = Number(section?.dataset.progress);
137+
133138
// Check if we're over a dark section
134-
const isDarkSection: boolean = !!elementBehind.closest(
135-
'[data-background="dark"]',
136-
);
139+
const isDarkSection =
140+
(sectionBackground === "light" && sectionAnimationProgress < 0.4) ||
141+
(sectionBackground === "dark" && sectionAnimationProgress >= 0.4);
137142

138143
// Toggle classes based on background
139144
nav.classList.toggle("text-orange-100", isDarkSection);

misc/landing-page/src/components/Section.astro

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const backgroundClass = background === "light" ? light : dark;
1313
---
1414

1515
<div
16-
class:list={["flex flex-col", backgroundClass]}
16+
class:list={["section-bg flex flex-col", background]}
1717
data-background={background}
1818
{...rest}
1919
>
@@ -27,3 +27,98 @@ const backgroundClass = background === "light" ? light : dark;
2727
<slot />
2828
</section>
2929
</div>
30+
31+
<style>
32+
@reference "../styles/global.css";
33+
34+
.light {
35+
@apply bg-light-20 text-brown-100;
36+
}
37+
38+
.dark {
39+
@apply bg-brown-90 text-white;
40+
}
41+
</style>
42+
43+
<script>
44+
function setupSectionAnimation() {
45+
// skip first section as it is the header
46+
const sections = [
47+
...document.querySelectorAll<HTMLElement>(".section-bg"),
48+
].slice(1);
49+
50+
let ticking = false;
51+
52+
function updateSectionVisibility(sectionIndex: number) {
53+
const section = sections[sectionIndex];
54+
const nextSection = sections.slice(sectionIndex + 1).find((section) => {
55+
return section.offsetHeight > 0;
56+
});
57+
58+
if (!nextSection) {
59+
return;
60+
}
61+
62+
const sectionBackground = section.dataset.background;
63+
64+
const rect = section.getBoundingClientRect();
65+
66+
const isBottomVisible = rect.bottom - window.innerHeight < 0;
67+
68+
const windowHeight = window.innerHeight * 0.35;
69+
70+
if (!isBottomVisible || section.offsetHeight === 0) {
71+
return;
72+
}
73+
74+
const progress = Math.max(
75+
Math.min((rect.bottom - windowHeight) / windowHeight, 1),
76+
0,
77+
);
78+
79+
if (nextSection.dataset.background === sectionBackground) {
80+
return;
81+
}
82+
83+
const fromColor =
84+
sectionBackground === "light"
85+
? "var(--color-light-20)"
86+
: "var(--color-brown-90)";
87+
const toColor =
88+
sectionBackground === "light"
89+
? "var(--color-brown-90)"
90+
: "var(--color-light-20)";
91+
92+
section.dataset.progress = progress.toString();
93+
section.style.backgroundColor = `color-mix(in oklab, ${fromColor} ${Math.round(progress * 100)}%, ${toColor})`;
94+
95+
nextSection.dataset.progress = (1 - progress).toString();
96+
nextSection.style.backgroundColor = `color-mix(in oklab, ${toColor} ${Math.round((1 - progress) * 100)}%, ${fromColor})`;
97+
}
98+
99+
function handleScroll() {
100+
if (!ticking) {
101+
requestAnimationFrame(() => {
102+
sections.forEach((_, i) => {
103+
updateSectionVisibility(i);
104+
});
105+
106+
ticking = false;
107+
});
108+
109+
ticking = true;
110+
}
111+
}
112+
113+
handleScroll();
114+
window.addEventListener("scroll", handleScroll);
115+
window.addEventListener("resize", handleScroll);
116+
}
117+
118+
function setup() {
119+
setupSectionAnimation();
120+
}
121+
122+
document.addEventListener("DOMContentLoaded", setup);
123+
document.addEventListener("astro:page-load", setup);
124+
</script>

0 commit comments

Comments
 (0)