Skip to content

Commit 04b094d

Browse files
committed
Update navbar script
Debouncing with requestAnimationFrame Minimum scroll threshold Top/bottom boundary handling State tracking Passive scroll listeners Orientation change handling Visibility API handling Smooth transitions
1 parent 88ba4c4 commit 04b094d

File tree

1 file changed

+79
-6
lines changed

1 file changed

+79
-6
lines changed

src/components/Header.astro

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,94 @@ import links from "@data/links.json";
4949

5050
<script>
5151
document.addEventListener("DOMContentLoaded", function() {
52-
var navbar = document.getElementById("navbar") as HTMLElement;
52+
const navbar = document.getElementById("navbar") as HTMLElement;
5353
if (!navbar) return;
5454

55-
var prevScrollPos = window.pageYOffset || document.documentElement.scrollTop;
55+
let prevScrollPos = window.pageYOffset || document.documentElement.scrollTop;
56+
let ticking = false;
57+
let isVisible = true;
5658

57-
window.addEventListener("scroll", function() {
58-
var currentScrollPos = window.pageYOffset || document.documentElement.scrollTop;
59+
// Ensure navbar is visible initially
60+
navbar.style.transform = "translateY(0)";
61+
navbar.style.transition = "transform 0.3s ease-in-out";
5962

60-
if (prevScrollPos > currentScrollPos) {
63+
function updateNavbar() {
64+
const currentScrollPos = Math.max(0, window.pageYOffset || document.documentElement.scrollTop);
65+
const documentHeight = document.documentElement.scrollHeight;
66+
const windowHeight = window.innerHeight;
67+
68+
// Don't hide navbar when at the very top
69+
if (currentScrollPos <= 10) {
70+
if (!isVisible) {
71+
navbar.style.transform = "translateY(0)";
72+
isVisible = true;
73+
}
74+
prevScrollPos = currentScrollPos;
75+
ticking = false;
76+
return;
77+
}
78+
79+
// Don't hide navbar when at the very bottom
80+
if (currentScrollPos + windowHeight >= documentHeight - 10) {
81+
if (!isVisible) {
82+
navbar.style.transform = "translateY(0)";
83+
isVisible = true;
84+
}
85+
prevScrollPos = currentScrollPos;
86+
ticking = false;
87+
return;
88+
}
89+
90+
// Only update if scroll difference is significant (helps with iOS bounce)
91+
const scrollDiff = Math.abs(currentScrollPos - prevScrollPos);
92+
if (scrollDiff < 5) {
93+
ticking = false;
94+
return;
95+
}
96+
97+
// Show navbar when scrolling up, hide when scrolling down
98+
if (prevScrollPos > currentScrollPos && !isVisible) {
6199
navbar.style.transform = "translateY(0)";
62-
} else {
100+
isVisible = true;
101+
} else if (prevScrollPos < currentScrollPos && isVisible) {
63102
navbar.style.transform = "translateY(-100%)";
103+
isVisible = false;
64104
}
65105

66106
prevScrollPos = currentScrollPos;
107+
ticking = false;
108+
}
109+
110+
function requestTick() {
111+
if (!ticking) {
112+
requestAnimationFrame(updateNavbar);
113+
ticking = true;
114+
}
115+
}
116+
117+
// Use passive listener for better performance on mobile
118+
window.addEventListener("scroll", requestTick, { passive: true });
119+
120+
// Handle orientation change on mobile devices
121+
window.addEventListener("orientationchange", function() {
122+
setTimeout(() => {
123+
prevScrollPos = Math.max(0, window.pageYOffset || document.documentElement.scrollTop);
124+
if (prevScrollPos <= 10) {
125+
navbar.style.transform = "translateY(0)";
126+
isVisible = true;
127+
}
128+
}, 100);
129+
});
130+
131+
// Handle page visibility changes (when switching tabs/apps)
132+
document.addEventListener("visibilitychange", function() {
133+
if (!document.hidden) {
134+
prevScrollPos = Math.max(0, window.pageYOffset || document.documentElement.scrollTop);
135+
if (prevScrollPos <= 10) {
136+
navbar.style.transform = "translateY(0)";
137+
isVisible = true;
138+
}
139+
}
67140
});
68141
});
69142
</script>

0 commit comments

Comments
 (0)